Introdução


Com este relatório pretendemos fazer uma análise sobre a COVID-19 em Portugal, com base nos dados da DGS disponíveis em: https://github.com/dssg-pt/covid19pt-data.

Este relatório tem como objetivo realizar uma análise detalhada dos seguintes tópicos:
  • Sintomas
  • Testagem
  • Casos
  • Mortes
  • Internamentos
  • Recuperação

Nota: Houve um lapso na base de dados e os óbitos cumulativos por idade e por sexo para dia 5/10 estão todos a 0. Subituimos esses 0’s pelos valores do dia anterior.

#Libraries
library(data.table)
#Libraries
library(data.table)
library(ggplot2)
library(grid)
library(dplyr)
library(grid)
library(dplyr)
library(tibble)
library(reshape2)
library(ggpubr)
library(tibble)
library(reshape2)
library(ggpubr)
library(maps)
library(reshape2)
library(ggpubr)
library(maps)
library(ggiraph)
library(leaflet)
library(geojsonio)
library(gganimate)
library(gganimate)
library(plotly)
library(RColorBrewer)
library(sf)
library(grid)
library(gridExtra)
library(htmltools)
library(htmltools)
library(zoo)
#Importar dados
covid19pt <- fread("https://raw.githubusercontent.com/dssg-pt/covid19pt-data/master/data.csv")

 [8%] Downloaded 7698 bytes...
 [20%] Downloaded 18657 bytes...
 [26%] Downloaded 24141 bytes...
 [29%] Downloaded 26883 bytes...
 [32%] Downloaded 29625 bytes...
 [35%] Downloaded 32367 bytes...
 [67%] Downloaded 62511 bytes...
 [70%] Downloaded 65253 bytes...
 [100%] Downloaded 92214 bytes...
library(gganimate)
library(plotly)
library(RColorBrewer)
library(sf)
library(grid)
library(gridExtra)
library(htmltools)
library(zoo)
#Importar dados
covid19pt <- fread("https://raw.githubusercontent.com/dssg-pt/covid19pt-data/master/data.csv")
covid19pt_testes <- fread("https://raw.githubusercontent.com/dssg-pt/covid19pt-data/master/amostras.csv")

 [100%] Downloaded 14009 bytes...

Sintomas


Na base de dados utilizada, as colunas 41 à 46 apresentam a percentagem de casos infetados que reportaram o sintoma respetivo. O comportamento dos dados leva-nos a crer que estes valores sejam cumulativos.

Estes dados só foram registados de dia 03/03/2020 até dia 16/08/2020 e, para além disso, tal como é referido na base de dados online, estes dados são relativos apenas a uma percentagem, não-especificada e variável, dos casos infetados. Por este motivo, apesar de termos realizado duas análises, estes resultados podem não ser fiáveis nem representativos da realidade.



Frequência Relativa


Os valores apresentadas neste gráfico de barras referem-se à percentagem de casos infetados que reportaram cada um dos sintomas. O sintoma mais frequente foi a tosse com 34% dos infetados a apresentarem esse sintoma, seguindo-se a febre com 27% e a cefaleia e dores musculares ambos com 20%.

Evolução da Frequência Relativa


Para entender melhor este gráfico é necessário perceber que os valores negativos indicam que houve uma diminuição na percentagem de pessoas com determinado sintoma clínico. Os valores positivos indicam que houve um aumento dessa percentagem sendo que os valores positivos menores do que o do dia anterior, significam que houve crescimento, mas menor.

Assim, é possível verificar que inicialmente existiu uma grande variação na frequência de casos confirmados que reportaram cada um dos sintomas. É de notar que a partir de junho esta variação foi sendo cada vez menor tornando os valores mais constantes, à exceção da tosse.


Testagem


Um dos fatores importantes a ter em conta é o número de pessoas testadas para a COVID-19. Assim sendo, utilizámos outra base de dados da mesma fonte para obter informações relativas à testagem.

É importante notar que os valores da base de dados “correspondem ao número de amostras processadas para diagnóstico de SARS-CoV-2 em laboratórios públicos e privados desde o dia 1 de março.” Para além disso, no dashboard da DGS dizem ainda que “Os dados diários após 2 de abril de 2020 ainda estão a ser recolhidos, pelo que os valores no gráfico poderão sofrer alterações.” Existe a possibilidade de, a cada dia, dados referentes a dias anteriores serem alterados, provavelmente pelo facto da informação relativa ao processamento de amostras ser recebida pela DGS com alguns dias de desfasamento.


Evolução do Número de Testes Realizados


Com a análise deste gráfico é possível verificar que o número de testes diários realizados tem vindo a demonstrar uma tendência crescente.

É ainda possível tirar outras conclusões, nomeadamente que os dias com menor testagem são maioritariamente o domingo, mas também o sábado, e que os dias com maior testagem são principalmente as terças e quartas.

Evolução da Taxa de Testes Positivos


Segundo o gráfico de linhas, em abril verificou-se a maior percentagem de testes positivos face ao número de testes totais, com valores perto dos 15%. A partir daí esta percentagem tem vindo a diminuir o que mostra que: há menos casos positivos e/ou há mais testes a serem realizados por dia. Nos últimos meses a percentagem foi quase sempre menor do que 5% o que, face aos meses anteriores, pode demonstrar que a testagem tem sido mais abrangente, sendo provável que se esteja a testar grande parte dos casos positivos.

Além disso, podemos ver que, principalmente ao domingo, a percentagem de testes positivos é constantemente maior face aos outros dias da semana. Esta informação é coerente com o gráfico anterior, uma vez que é nestes dias que se verifica um menor número de testes diários e assim, supomos que dão primazia aos casos mais urgentes, aumentando assim a percentagem de testes positivos ao domingo. O contrário verifica-se à terça, dia em que são testadas mais pessoas, existindo normalmente uma menor percentagem de testes positivos.


Casos


Neste tópico vamos abordar a incidência (número de novos casos diários), a taxa de incidência (número de novos casos diários/população em risco), número de casos cumulativos em valor absoluto e prevalência (número total de casos/população).


Geral

Evolução da Incidência


Na linha da incidência é possível ver que o número de casos diários teve um pico no dia 10/04/2020. Uma vez que o número de testes não aumentou de forma significativa nos dias anteriores, uma das justificações possíveis é ter ocorrido um lapso na notificação dos casos nesse dia.

Podemos ainda constatar um ligeiro aumento no número de casos durante os meses de maio e junho. Este aumento pode ser justificado na sequência do período de férias, que apesar das restrições impostas, leva sempre a um aumento das deslocações e a um maior número de contactos entre pessoas. A diminuição da incidência verificada entre julho e agosto pode ser justificada pelo facto dos possíveis infetados com sintomas ligeiros não recorrerem à linha de saúde 24, por não quererem fazer um isolamento profilático durante as suas férias.

À data desta análise, desde o início de setembro, a subida do número de casos tem sido crescente, sendo possíveis justificações:
  • Regresso dos trabalhadores ao emprego presencial
  • Regresso dos jovens às escolas
  • Aumento da testagem sobretudo a partir de dia 08/09/2020
  • Regresso a uma vida mais normal com mais contactos entre pessoas e menos cuidados e preocupações do que no início da pandemia

No gráfico da Evolução da Taxa de Testes Positivos, é possível ver que, desde o início de setembro, tem havido um aumento na percentagem de casos positivos. No entanto, não é um aumento tão acentuado como aquele verificado neste gráfico da Evolução da Incidência. Isto indica-nos que o aumento do número de casos não é totalmente explicado pelo aumento do número de testes realizados.

Administração Regional de Saúde (ARS)

Número de Casos


Neste gráfico e mapa podemos ver que Lisboa e Vale do Tejo é a ARS com mais casos, seguindo-se a ARS Norte. Com menos casos, é de realçar os Açores e a Madeira que, com as estratégias implementadas para os turistas que obrigam a realização de um teste ao SARS-CoV-2 negativo até 72h antes da ida ou a realização do teste à chegada ao aeroporto, cumprindo o isolamento profilático até à receção do resultado do mesmo, conseguiram limitar o aumento do número de casos. No entanto, temos de ter presente que este gráfico e mapa não têm em consideração a população de cada ARS.

Evolução da Incidência


Com a interpretação deste gráfico de linhas, podemos ver que as ARSs do Norte e do Centro têm tido um comportamento semelhante. Ambas tiveram um grande aumento em abril, tendo-se mantido estáveis durante os meses de verão, começando a aumentar de novo em setembro. No entanto, é importante realçar que no iníco da pandemia a ARS do Norte apresentou um número de novos casos muito superior a todas as outras ARSs, pois foi onde surgiram os primeiros surtos deste vírus em Portugal.

A ARS de Lisboa e Vale do Tejo, por outro lado, não apresentou tantos casos diários em abril como a ARS do Norte tendo iniciado o confinamento com menor número de casos. Em maio, com o fim do confinamento, é notável um aumento considerável no número de novos casos que se prolongou até julho. No verão a incidência sofreu um decréscimo, que pode ser resultado de deslocações para outras regiões durante o período de férias. A partir setembro, com o fim das férias e o regresso às escolas e à atividade profissional, a incidência tem vindo a apresentar valores mais elevados.

Relativamente às ARSs do Alentejo e do Algarve, podemos verificar um aumento significativo do número de novos casos a partir de meados de junho, correspondente ao período de férias. Como em todas as outras ARSs de Portugal continental, a incidência tem vindo a aumentar desde o início de setembro pelas mesmas razões apresentadas anteriormente.

Quanto aos Açores e à Madeira, é notável a ausência quase total de novos casos durante os meses de maio e junho, resultado de uma testagem massiva com adequado controlo dos casos iniciais e da implementação de medidas contenção, como a quarentena obrigatória e permissão de entrada exclusiva a residentes. A partir de julho, voltaram a surgir alguns casos devido ao levantamento da restrição à entrada de turistas. É também de realçar que são as únicas regiões que não têm sofrido um aumento desde setembro.

#Fazer tabela com número de casos diários por região
incidencia_regioes_tempo <- cbind(covid19pt$data, (as.data.frame(covid19pt[, confirmados_arsnorte:confirmados_madeira] -lag(covid19pt[,confirmados_arsnorte:confirmados_madeira]))))
names(incidencia_regioes_tempo) =  c("Data", "Norte", "Centro", "LVT", "Alentejo", 
                                     "Algarve", "Açores", "Madeira")
incidencia_regioes_tempo_melt <- melt(incidencia_regioes_tempo, id.vars = "Data")
names(incidencia_regioes_tempo_melt) = c("Data", "Regiao", "Incidencia")

#Fazer gráfico de linhas com data no eixo do x, a incidencia no eixo do y e o género em cada linha
incidencia_regioes_tempo_grafico <- ggplot(incidencia_regioes_tempo_melt, aes(x = Data, y = Incidencia, color = Regiao)) +
  geom_point(aes(text = paste('Data: ', Data,
                              '<br>ARS: ', Regiao,
                              '<br>Incidência: ', Incidencia)), size = 0.1) +
  geom_line(size = 0.5) +
  labs(x = "") +
  theme(axis.text.y = element_text(size = 8),
        axis.text.x = element_text(size = 7),
        legend.position = "none") +
  scale_x_date(breaks = "3 months", date_labels = "%b %d")

#Tornar interativo
incidencia_regioes_tempo_grafico_interativo <- ggplotly(incidencia_regioes_tempo_grafico, tooltip = "text") %>% 
    layout(yaxis = list(title = paste0(c(rep("&nbsp;", 20),
                                       "Incidência",
                                       rep("&nbsp;", 20),
                                       rep("\n&nbsp;", 2)),
                                     collapse = "")))

#Incidência com média rolante 7 dias
##Fazer a média rolante
incidencia_regioes_tempo_media_rolante <- cbind(incidencia_regioes_tempo[7:nrow(incidencia_regioes_tempo),1],
                                                as.data.frame(rollmean(incidencia_regioes_tempo[,2:8], k = 7)))
names(incidencia_regioes_tempo_media_rolante)[1] = "Data"

incidencia_regioes_tempo_media_rolante_melt <- melt(incidencia_regioes_tempo_media_rolante, id.vars = "Data")
names(incidencia_regioes_tempo_media_rolante_melt) = c("Data", "Regiao", "Incidencia")

##Fazer gráfico
incidencia_regioes_tempo_media_rolante_melt_grafico <- ggplot(incidencia_regioes_tempo_media_rolante_melt, 
                                                              aes(x = Data, y = Incidencia, color = Regiao)) +
  geom_point(aes(text = paste('Data: ', Data,
                              '<br>ARS: ', Regiao,
                              '<br>Incidência: ', Incidencia)), size = 0.1) +
  geom_line(size=0.5) +
  theme(legend.title = element_blank(),
        axis.text.y = element_text(size = 8),
        axis.text.x = element_text(size = 7)) +
  labs(title = "Média Rolante (7 dias)",
       x = "",
       y = "Incidência") +
  scale_x_date(breaks = "3 months", date_labels = "%b %d")

##Tornar gráfico interativo
incidencia_regioes_tempo_media_rolante_melt_grafico_interativo <- ggplotly(incidencia_regioes_tempo_media_rolante_melt_grafico, tooltip = "text") %>% 
  layout(yaxis = list(title = paste0(c(rep("&nbsp;", 20),
                                       "Incidência",
                                       rep("&nbsp;", 20),
                                       rep("\n&nbsp;", 2)),
                                     collapse = "")),
         legend = list(x = 1, y = 0))


#mapa
##Fazer tabela com novos casos mais recentes
incidencia_regioes_recente <- as.data.frame(t(as.data.frame(
  lapply((covid19pt[, confirmados_arsnorte:confirmados_madeira])
         - lag(covid19pt[, confirmados_arsnorte:confirmados_madeira]), last)))) %>% 
  rownames_to_column(var = "Regioes")
incidencia_regioes_recente[,1] = c("Norte", "Centro", "Lisboa e Vale do Tejo", "Alentejo", 
                                   "Algarve", "Açores", "Madeira")

##Definir intervalos para legenda
bins_7 =  c(0, 50, 300, 500, 800, 1000, 1500, 2000, Inf)

##Definir palete de cores para mapa
pal_7 <- colorBin("YlOrRd", domain = incidencia_regioes_recente[,2], bins = bins_7)

##Da tabela anterior com todas as datas, selecionar apenas o valor mais recente e mudar nome coluna e Regiãoes
incidencia_regioes_recente <- incidencia_regioes_recente[c(4, 5, 6, 2, 7, 1, 3),] 

##Definir legenda quando se passa com o rato por cima
labels_7 <- sprintf(
  "<strong>%s</strong><br/>%g casos novos",
  incidencia_regioes_recente[,1], round(incidencia_regioes_recente[,2], digits = 4)
) %>% lapply(htmltools::HTML)


##Fazer o mapa
incidencia_regioes_mapa <- leaflet(mapa_pt) %>% 
  addTiles(group = "Normal") %>% 
  addProviderTiles(providers$CartoDB.Positron, group = "Claro") %>% 
  addProviderTiles(providers$CartoDB.DarkMatterNoLabels, group = "Escuro") %>% 
  addLayersControl(
    baseGroups = c("Normal", "Claro", "Escuro"),
    options = layersControlOptions(collapsed = TRUE)
  ) %>% 
  addPolygons(
    fillColor = ~pal_7(incidencia_regioes_recente[,2]), 
    weight = 2,
    opacity = 1,
    color = "white",
    dashArray = "3",
    fillOpacity = 0.7,
    highlight = highlightOptions(
      weight = 5,
      color = "#666",
      dashArray = "",
      fillOpacity = 0.7,
      bringToFront = TRUE),
    label = labels_7,
    labelOptions = labelOptions(style = list("font-weight" = "normal", 
                                             padding = "3px 8px"),
                                textsize = "15px",
                                direction = "auto")) %>% 
  addLegend(pal = pal_7, values = incidencia_regioes_recente[,2], opacity = 0.7, title = "Incidência Atual por ARS",
            position = "bottomright")

#Incidência com média rolante 14 dias
##Fazer a média rolante
incidencia_regioes_tempo_media_rolante_14 <- cbind(incidencia_regioes_tempo[14:nrow(incidencia_regioes_tempo),1],
                                                as.data.frame(rollmean(incidencia_regioes_tempo[,2:8], k = 14)))
names(incidencia_regioes_tempo_media_rolante_14)[1] = "Data"

incidencia_regioes_tempo_media_rolante_14_melt <- melt(incidencia_regioes_tempo_media_rolante_14, id.vars = "Data")
names(incidencia_regioes_tempo_media_rolante_14_melt) = c("Data", "Regiao", "Incidencia")

##Fazer gráfico
incidencia_regioes_tempo_media_rolante_14_melt_grafico <- ggplot(incidencia_regioes_tempo_media_rolante_14_melt, 
                                                              aes(x = Data, y = Incidencia, color = Regiao)) +
  geom_point(aes(text = paste('Data: ', Data,
                              '<br>ARS: ', Regiao,
                              '<br>Incidência: ', Incidencia)), size = 0.1 ) +
  geom_line(size=0.5) +
  theme(legend.title = element_blank(),
        axis.text.y = element_text(size = 8),
        axis.text.x = element_text(size = 7)) +
  labs(title = "Média Rolante (14 dias)",
       x = "",
       y = "Incidência") +
  scale_x_date(breaks = "3 months", date_labels = "%b %d")

##Tornar gráfico interativo
incidencia_regioes_tempo_media_rolante_14_melt_grafico_interativo <- ggplotly(incidencia_regioes_tempo_media_rolante_14_melt_grafico, tooltip = "text") %>% 
  layout(yaxis = list(title = paste0(c(rep("&nbsp;", 20),
                                       "Incidência",
                                       rep("&nbsp;", 20),
                                       rep("\n&nbsp;", 2)),
                                     collapse = "")),
         legend = list(x = 1, y = 0))


browsable(
  tagList(list(
    tags$div(
      style = 'width:50%;display:block;float:left;',
      incidencia_regioes_tempo_grafico_interativo
    ),
    tags$div(
      style = 'width:50%;display:block;float:left;',
      incidencia_regioes_tempo_media_rolante_melt_grafico_interativo
    )
  ))
)


browsable(
  tagList(list(
    tags$div(
      style = 'width:50%;display:block;float:left;',
      incidencia_regioes_tempo_media_rolante_14_melt_grafico_interativo
    ),
    tags$div(
      style = 'width:50%;display:block;float:left;',
      incidencia_regioes_mapa
    )
  ))
)

Evolução da Taxa de Incidência


Com este gráfico de linhas conseguimos ver a evolução temporal das diferentes taxas de incidência para cada ARS.

As regiões dos Açores e da Madeira são as que têm as taxas de incidência mais baixas e mais constantes.

As ARSs do Algarve e do Alentejo têm um comportamento muito semelhante entre si. Tiveram um aumento em abril, como todas as outras ARSs, sofrendo uma diminuição posteriormente e mantendo-se constantes até ao iníco do verão. Como podemos ver, nestas duas ARSs muito procuradas como destino de férias, as taxas de incidência aumentaram logo a partir de junho. Contudo, a ARS do Alentejo mostra alguns picos no verão que podem ser referentes aos surtos em lares.

A ARS do Centro é, das ARSs de Portugal continental, a única que se tem mantido constante deste setembro, sem grandes variações.

A ARS do Norte foi a que teve uma maior taxa de incidência em abril, tendo estabilizado em meados de maio. Desde setembro voltou a subir de forma considerável.

A ARS de Lisboa e Vale do Tejo é a que tem o comportamento mais díspar e preocupante. Sem nunca ter diminuído a taxa de incidência de forma tão acentuada como as outras ARSs, manteve-se com oscilações recorrentes ao longo do verão. Esta começou a subir a partir de setembro, apresentando o maior valor desde o início da pandemia.

#Valores da população de cada Região com base nas CCDRs
acores = 242796
alentejo = 503507
algarve = 450484
centro = 2217285
lisboa = 3631738
madeira = 253945
norte = 3575338

#Criar uma tabela com uma coluna para as Regiãoes e outra para o número de pessoas nessa Região
populacao_regioes <- as.data.frame(c(norte, centro, lisboa, alentejo, algarve, acores, madeira), 
                                   c("norte", "centro", "lisboa", "alentejo", "algarve", "açores", "madeira"))
colnames(populacao_regioes) <- "População"

###Fazer com que cada coluna seja uma Região e repetir cada número as vezes necessárias para ficar com o número igual ao das colunas da base de dados
populacao_regioes_rep <- as.data.frame(t(populacao_regioes[rep(seq_len(ncol(populacao_regioes)), each = nrow(covid19pt))]))

###Calcular a incidência em cada Região fazendo os casos novos por Região a dividir pela população da Região menos os confirmados da Região menos os óbitos da Região e dar nomes a cada coluna
incidencia_regioes <- cbind(covid19pt$data, (as.data.frame(covid19pt[, confirmados_arsnorte:confirmados_madeira] 
                                                      - lag(covid19pt[, confirmados_arsnorte:confirmados_madeira]))) 
                            / (populacao_regioes_rep - as.data.frame(covid19pt[,confirmados_arsnorte:confirmados_madeira])))
names(incidencia_regioes) <- c("Data", "Norte", "Centro", "Lisboa e Vale do Tejo", "Alentejo", "Algarve",
                               "Açores", "Madeira")

###Fazer melt para fazer o gráfico e dar nomes a cada coluna
incidencia_regioes_melt <- melt(incidencia_regioes, id.vars = "Data")
names(incidencia_regioes_melt) <- c("data", "regiao", "valor")

###Fazer o gráfico de linhas com a data no eixo do x, a incidência no eixo do y e a Região em cada linha
ggplot(incidencia_regioes_melt, aes(x = data, y = valor*100, color = regiao)) +
  geom_line() + 
  labs(x = "", 
       y = "Taxa de Incidência (%)") +
  facet_grid(incidencia_regioes_melt$regiao) +
  theme(axis.title.x = element_text(margin = margin(t = 15, b = 10), 
                                    size = 12),
        axis.title.y = element_text(margin = margin(r = 15, l = 10), 
                                    size = 12),
        axis.text.y = element_text(size = 5),
        strip.text.y = element_text(size = 8, angle = 0)) +
  guides(color = FALSE) +
  scale_x_date(breaks = "3 months", date_labels = "%b %d")

Taxa de Incidência Cumulativa


Como é possível verificar com a análise deste gráfico de barras e mapa, as ARSs de Lisboa e Vale do Tejo e do Norte apresentam valores de prevalência bastante superiores às outras ARSs. Desta forma, concluímos que, apesar de serem as ARSs com maior população, não é este fator que justifica diretamente o elevado número de casos.

Relativamente às ARSs do Algarve e do Alentejo, apesar de serem as ARSs com menor população de Portugal continental, têm as terceiras e quartas prevalências mais elevadas, respetivamente. Isto pode ser justificado pelo facto de ambas as ARSs serem destinos de eleição de férias, tendo sofrido um aumento da incidência durante o verão (gráfico da Evolução da Incidência por ARS). O facto de os turistas não serem contabilizados na população destas ARSs, contribui para o aumento da prevalência (isto se o turista for considerado confirmado na ARS onde testou positivo).

Como referido anteriormente, as baixas prevalências dos Açores e da Madeira confirmam o sucesso das medidas implementadas.

populacao_regioes_invertido <- t(populacao_regioes)

prevalencia_regiao <- (as.data.frame(t(as.data.frame((lapply(covid19pt[,confirmados_arsnorte:confirmados_madeira], last)))))*100 / populacao_regioes_invertido) %>% 
  rownames_to_column(var="Regiao")
colnames(prevalencia_regiao)[2] <- "Prevalencia"
prevalencia_regiao[,1] <- c("Norte", "Centro", "LVT", "Alentejo", "Algarve", "Açores", "Madeira")

prevalencia_regiao_grafico <- ggplot(prevalencia_regiao, aes(x=Regiao, y=Prevalencia)) + 
  geom_col(fill="palegreen", width = 0.5, aes(text = paste('ARS: ', Regiao,
                              '<br>Taxa de Incidência Cumulativa (%): ', Prevalencia))) +
  scale_y_continuous(expand = c(0, 0)) +
  theme_classic() +
  labs(y="Prevalência (%)", x="") +
  theme(axis.title.y = element_text(size = 12))

prevalencia_regiao_grafico_interativo <- ggplotly(prevalencia_regiao_grafico, tooltip = "text") %>% 
  layout(yaxis = list(title = paste0(c(rep("&nbsp;", 20),
                                       "Taxa de Incidência Cumulativa (%)",
                                       rep("&nbsp;", 20),
                                       rep("\n&nbsp;", 2)),
                                     collapse = "")))
#Mapa
prevalencia_regiao_ordem <- prevalencia_regiao[c(4,5,6,2,7,1,3),] # colocar as regioes pela ordem do mapa
prevalencia_regiao_ordem[,1] <- c("Alentejo", "Algarve", "Açores", "Centro", "Madeira", "Norte", "Lisboa e Vale do Tejo" )

pal_prevalencia_regiao <- colorBin("viridis", domain = prevalencia_regiao_ordem$Prevalencia, bins = c(0.1, 0.3, 0.5, 0.8, 1, 1.3, 1.5, Inf))

labels_prevalencia_regiao <- paste( 
  "<strong>", prevalencia_regiao_ordem[,1],"</strong><br/>", 
  round(prevalencia_regiao_ordem[,2], digits = 4), "&#37<br/>", 
  sep="") %>%
  lapply(htmltools::HTML)

prevalencia_regiao_mapa <- leaflet(mapa_pt) %>%
  addPolygons(stroke = TRUE, 
              smoothFactor = 0.3, 
              fillOpacity = 1, 
              color = "black", 
              weight = 1,
              fillColor = ~pal_prevalencia_regiao(prevalencia_regiao_ordem$Prevalencia),
              label = labels_prevalencia_regiao, 
              labelOptions = labelOptions(style = list("font-weight" = "normal", padding = "3px 8px"), 
                                          textsize = "13px", 
                                          direction = "auto")) %>% 
  addLegend("bottomleft", 
            pal = pal_prevalencia_regiao, 
            values = prevalencia_regiao_ordem$Prevalencia , 
            opacity = 0.5, 
            title = "Taxa de Incidência Cumulativa (%) por ARS") %>% 
  addTiles(group ="Original") %>%
  addProviderTiles(providers$CartoDB.Positron, group = "Positron") %>%
  addProviderTiles(providers$Esri.WorldImagery, group = "Satélite") %>%
  addLayersControl(baseGroups = c("Original", "Positron", "Satélite"), options = layersControlOptions(collapsed = FALSE))

browsable(
  tagList(list(
    tags$div(
      style = 'width:50%;display:block;float:left;',
      prevalencia_regiao_mapa
    ),
    tags$div(
      style = 'width:50%;display:block;float:left;',
      prevalencia_regiao_grafico_interativo
    )
  ))
)

Faixa Etária e Género

Número de Casos por Faixa Etária e por Género


Neste gráfico podemos ver que a maior parte dos casos existentes são das faixas etárias entre os 20 e os 59 anos. Este valor parece fazer sentido uma vez que corresponde à população ativa, geralmente a população mais exposta. No entanto, é importante realçar que, por ser um valor absoluto, não têm em consideração a população de cada faixa etária, o que significa que pode haver mais casos nestas idades por serem simultaneamente as faixas etárias com maior número de pessoas em Portugal.

Por outro lado, é visível que, em todas as faixas etárias, o género feminino é o que tem maior número de casos, com exceção do grupo etário dos 0 aos 9 anos. Esta assimetria pode ser explicada por, em muitas das profissões com grande exposição ao vírus, a maioria dos trabalhadares são mulheres. Novamente, estes dados podem não ser estatisticamente fiáveis por não se ter tido em conta a população existente de cada género.

#Selecionar as colunas de confirmados feminino para todas as idades e juntá-las numa tabela e fazer o mesmo para o masculino
femininos <- as.data.frame(covid19pt %>% 
                             dplyr::select(starts_with("confirmados_") & (ends_with("9_f")| ends_with("plus_f"))))
masculinos <- as.data.frame(covid19pt %>% 
                              dplyr::select((starts_with("confirmados_") & (ends_with("9_m")| ends_with("plus_m")))))

#Selecionar o valor mais recente de cada coluna de modo a ficar com o número de casos até ao momento para cada faixa etária e para cada género
casos_femininos_idade <- as.data.frame(lapply(femininos, last))
casos_masculinos_idade <- as.data.frame(lapply(masculinos, last))

#Criar tabela com uma colunda para a faixa etária e outra para o número de casos femininos e mudar coluna da faixa etária para os nomes adequados
casos_femininos_idade_invertido <- as.data.frame(t(casos_femininos_idade)) %>% 
  rownames_to_column(var = "Idade")
names(casos_femininos_idade_invertido)[2] <- "Feminino"
casos_femininos_idade_invertido[,1] <- c("0-9", "10-19", "20-29", "30-39", "40-49", "50-59", "60-69", "70-79", "80+")

#Criar tabela com uma colunda para a faixa etária e outra para o número de casos masculinos e mudar coluna da faixa etária para os nomes adequados
casos_masculinos_idade_invertido <- as.data.frame(t(casos_masculinos_idade)) %>% 
  rownames_to_column(var = "Idade")
names(casos_masculinos_idade_invertido)[2] <- "Masculino"
casos_masculinos_idade_invertido[,1] <- c("0-9", "10-19", "20-29", "30-39", "40-49", "50-59", "60-69", "70-79", "80+")

#Juntar as 3 tabelas que criámos
casos_fem_masc <- merge(casos_femininos_idade_invertido, casos_masculinos_idade_invertido, by = "Idade")

#Fazer melt para poder fazer gráfico 
casos_fem_masc_melt <- melt(casos_fem_masc, id.vars = "Idade")
names(casos_fem_masc_melt) = c("Idade", "Genero", "Casos")

###Fazer gráfico de barras com idade no eixo do x, o número de casos no eixo do y e o género em cada barra
casos_fem_masc_grafico <- ggplot(casos_fem_masc_melt, aes(x = Idade, y = Casos, fill = Genero)) +
  geom_col(position = "dodge", aes(text = paste('Faixa Etária: ', Idade,
                              '<br>Género: ', Genero,
                              '<br>Nº de Casos: ', Casos))) +
  scale_y_continuous(expand = c(0, 0)) +
  coord_cartesian(ylim = c(0, max(casos_fem_masc_melt$Casos + 1000))) +
  theme_classic() +
  labs(x = "",
       y = "Mortes") +
  theme(legend.title = element_blank(),
        axis.title.x = element_text( size = 12),
        axis.text.x = element_text(size=8, 
                                   color = "black"),
        axis.text.y = element_text(size=10,
                                   color = "black")) +
  guides(fill=guide_legend(title="Género")) +
  scale_fill_manual(values = c("deeppink3", "lightblue", "grey60"))

#Fazer gráfico interativo
ggplotly(casos_fem_masc_grafico, tooltip = "text") %>% 
  layout(yaxis = list(title = paste0(c(rep("&nbsp;", 20),
                                       "Número de Casos",
                                       rep("&nbsp;", 20),
                                       rep("\n&nbsp;", 2)),
                                     collapse = "")),
         legend = list(x = 1, y = 0))

Evolução da Incidência por Faixa Etária


Neste gráfico de área podemos verificar que as faixas etárias entre os 0 e os 19 anos, apresentaram inicialmente um baixo número de novos casos diários. Nos meses de verão verificou-se um aumento do número de casos, que se tornou mais expressivo a partir de setembro, o que poderá ser explicado pelo regresso dos estudantes às aulas e pelo regresso dos pais aos empregos.

Relativamente às faixas etárias entre os 20 e os 59 anos, estas apresentaram um comportamento semelhante, uma vez que correspondem à população ativa, mantendo-se o número de novos casos diários em torno dos mesmos valores.

Nas faixas etárias a partir dos 60 anos, é possível verificar que no mês de abril houve um maior número de novos casos diários, o que coincidiu com os surtos iniciais da doença, nomeadamente nos lares. De seguida, houve uma diminuição da incidência provavelmente devido a uma crescente preocupação pela proteção dos grupos etários de risco. A partir de setembro, é de notar um novo crescimento no número de casos diários, podendo isto ser justificado por um maior contacto com faixas etárias mais ativas (filhos e netos).

#Pegando nas tabelas que fizémos por género or faixa etária, como os valores na base de dados são cumulativos, fazemos o valor desse dia menos o valor do dia anterior para obtermos o número de novos casos por dia, por faixa etária por género
femininos_novos <- femininos - lag(femininos)
masculinos_novos <- masculinos - lag(masculinos)

#Criar uma tabela com uma coluna para a data e outras colunas com o número de casos por dia por faixa etária apenas que resultam da soma dos novos casos femininos com os novos casos masculinos
casos_total_tempo <- cbind(covid19pt$data, as.data.frame(femininos_novos + masculinos_novos))

#Como  linha 7 que é a primeira em que há registo dos casos já representa o número de casos nesse dia apenas, adicionámos essa linha à tabela e dar nomes às colunas
casos_total_tempo[7, 2:10] <- femininos[7,] + masculinos[7,]
names(casos_total_tempo)<- c("Data", "0-9", "10-19", "20-29", "30-39", "40-49", "50-59", "60-69", "70-79", "80+")

#Fazer melt para fazer o gráfico
casos_total_tempo_melt <- melt(casos_total_tempo, id.vars = "Data")
names(casos_total_tempo_melt) = c("Data", "Faixa_Etaria", "Casos")

#Fazer o gráfico de área com a data no eixo do x, o número de casos no eixo do y e a faixa etária em cada linha
casos_total_tempo_grafico <- ggplot(casos_total_tempo_melt, aes(x = Data, y = Casos, fill = Faixa_Etaria)) +
  geom_area(alpha=0.6 , size=.5) +
  labs(x ="", 
       y = "Incidência") +
  theme(legend.title = element_blank(),
        axis.title.x = element_text(size = 12),
        axis.title.y = element_text(size = 12),
        axis.text.y = element_text(size = 5),
        strip.text.y = element_text(size = 3, angle = 0)) +
  scale_x_date(breaks = "months", date_labels = "%b")

#Tornar gráfico interativo
casos_total_tempo_grafico_interativo <- ggplotly(casos_total_tempo_grafico) %>% 
  layout(legend = list(x = 1, y = 0))

#Número de casos com média rolante
##Calcular a média rolante
casos_total_tempo_media_rolante <- cbind(casos_total_tempo[7:nrow(casos_total_tempo),1], 
                                         as.data.frame(rollmean(casos_total_tempo[,2:10],k = 7)))
names(casos_total_tempo_media_rolante)[1] = "Data"

##Fazer melt
casos_total_tempo_media_rolante_melt <- melt(casos_total_tempo_media_rolante, id.vars = "Data")
names(casos_total_tempo_media_rolante_melt) = c("Data", "Faixa_Etaria", "Casos")

##Fazer gráfico de linhas
casos_total_tempo_media_rolante_grafico_linhas <- ggplot(casos_total_tempo_media_rolante_melt, 
                                                         aes(x = Data, y = Casos, color = Faixa_Etaria)) +
  geom_point(size=0.1, aes(text = paste('Data: ', Data,
                              '<br>Faixa Etária: ', Faixa_Etaria,
                              '<br>Incidência: ', Casos))) +
  geom_line(size=0.5) +
  labs(title = "Média Rolante (7 dias)",
       x ="", 
       y = "Incidência") +
  theme(legend.title = element_blank(),
        axis.title.x = element_text(size = 12),
        axis.title.y = element_text(size = 12),
        axis.text.y = element_text(size = 5),
        strip.text.y = element_text(size = 3, angle = 0)) +
  scale_x_date(breaks = "3 months", date_labels = "%b %d")

##Tornar gráfico interativo
casos_total_tempo_media_rolante_grafico_linhas_interativo <- ggplotly(casos_total_tempo_media_rolante_grafico_linhas, tooltip = "text")
 


browsable(
  tagList(list(
    tags$div(
      style = 'width:50%;display:block;float:left;',
      casos_total_tempo_grafico_interativo
    ),
    tags$div(
      style = 'width:50%;display:block;float:left;',
      casos_total_tempo_media_rolante_grafico_linhas_interativo
    )
  ))
)

Evolução Taxa de Incidência por Faixa Etária


Novamente neste gráfico, é possível observar que as faixas etárias dos 0 aos 19 anos apresentaram uma baixa taxa de incidência, mesmo nos primeiros meses da pandemia, tendo-se mantido relativamente estável. Desde setembro, estes valores têm aumentado na sequência do início do período escolar.

No caso das faixas etárias entre os 20 e os 39 anos, inicialmente apresentaram valores de taxa de incidência mais elevados, diminuindo posteriormente mas sempre com alguma instabilidade, não só por pertencerem a uma fração ativa da população, mas também pela maior tendência para frequentar locais com maiores aglomerados de indivíduos. Dos 40 aos 59 anos o comportamento da curva é semelhante, no entanto manteve-se mais ou menos constante durante os meses de Verão, tendo voltado a aumentar a partir de setembro, o que mimetiza o comportamento das faixas etárias anteriores.

Relativamente às faixas etárias dos 60 aos 79 anos, podemos verificar que a taxa de incidência foi principalmente preocupante nos meses iniciais da pandemia, tendo depois estabilizado até meados de setembro, novamente resultante de uma crescente preocupação pelo grupo etário mais suscetível. Da mesma forma, a faixa etária dos 80+ apresentou uma taxa de incidência inicial alarmante, no entanto nunca conseguiu estabilizar da mesma forma, provavelmente decorrente de diversos surtos em lares ao longo do tempo.

#Dados da população de portugal em <https://www.pordata.pt/Portugal/Popula%C3%A7%C3%A3o+residente++m%C3%A9dia+anual+total+e+por+grupo+et%C3%A1rio-10>
pt_0_9 = 433332 + 461299
pt_10_19 = 507646 + 549033
pt_20_29 = 544575 + 547505
pt_30_39 = 571355 + 679093
pt_40_49 = 792670 + 782555
pt_50_59 = 747581 + 734540
pt_60_69 = 672758 + 620543
pt_70_79 = 544016 + 429107
pt_80_plus = 352218 + 316442

#Fazer tabela com população por faixa etária
populacao_idades_pt <- as.data.frame(c(pt_0_9, pt_10_19, pt_20_29, pt_30_39, pt_40_49, pt_50_59, pt_60_69, pt_70_79, pt_80_plus))

##Repetir valores da população por faixa etária para ficar com mesmo número de linhas da base de dados
populacao_idades_pt_rep <- as.data.frame(t(populacao_idades_pt[rep(seq_len(ncol(populacao_idades_pt)), each = nrow(covid19pt))]))

#Calcular a população de risco subtraindo à população por faixa etária o número de óbitos e o número de casos até ao momento                
populacao_risco_idade <- populacao_idades_pt_rep - femininos - masculinos

#Calcular a taxa de incidência, retirando a coluna das datas
taxa_incidencia_idade <- (casos_total_tempo[,-1]/populacao_risco_idade)*100

#Voltar a adicionar a coluna da data e fazer melt para fazer o gráfico
taxa_incidencia_idade <- cbind(covid19pt$data, taxa_incidencia_idade)
names(taxa_incidencia_idade)[1] = "Data"
taxa_incidencia_idade_melt <- melt(taxa_incidencia_idade, id.vars = "Data")
names(taxa_incidencia_idade_melt) = c("Data", "Faixa_Etaria", "Taxa_Incidencia")

#Fazer gráfico de linhas com data no eixo do x, taxa de incidência no eixo do y e faixa etária nas cores das linhas
ggplot(taxa_incidencia_idade_melt, aes(x = Data, y = Taxa_Incidencia, color = Faixa_Etaria)) +
  geom_line(size = 0.8)+
  facet_grid(taxa_incidencia_idade_melt$Faixa_Etaria)+
  guides(color = FALSE) +
  labs(x = "",
       y ="Taxa de Incidência (%)") +
  theme(axis.title.y = element_text(margin = margin(r = 20, l = 20),
                                    size = 12),
        axis.text.y = element_text(size = 8),
        strip.text.y = element_text(size = 8, angle = 0)) +
  scale_x_date(breaks = "3 months", date_labels = "%b %d")

Taxa de Incidência Cumulativa por Faixa Etária


Neste gráfico de barras é possível ver que, à data desta análise, a faixa etária com maior prevalência é a dos 80+ anos. Isto pode ser explicado pelo facto de esta faixa etária necessitar de mais cuidados, estando presente em lares (onde têm ocorrido surtos) ou recorrendo a cuidadores, sendo por isso mais suscetíveis à infeção.

A faixa etária dos 20 aos 29 anos é a que apresenta a segunda maior prevalência, sendo notório que este valor vai diminuindo à medida que se progride na faixa etária, com exceção da faixa etária dos 80+, pelo explicado anteriormente. Isto pode dever-se ao aumento do receio da doença com o aumento da idade.

As faixas etárias entre os 9 e os 19 anos são as que têm as prevalências mais baixas, o que pode ser explicado pelo encerramento das escolas que promoveu uma maior proteção das crianças. É ainda prematuro tirar conclusões sobre o impacto que a reabertura das escolas terá na prevalência destas faixas etárias.

Relativamente à evolução da prevalência por faixa etária, em abril é visível que a faixa etária dos 80+ anos era a que tinha, de longe, a maior prevalência. É de notar tabém que desde setembro que todas as faixa etárias sofreram um maior aumento da prevalência comparado com os meses anteriores.

###Somar a tabela dos femininos com a dos masculinos o que vai dar o número de casos até ao momento por idade apenas
casos_total_idade <- as.data.frame(casos_femininos_idade + casos_masculinos_idade)

#Calcular prevalência
prevalencia_idade <- ((as.data.frame(t(casos_total_idade)))*100 / populacao_idades_pt) %>%  
  rownames_to_column(var = "Faixa_Etaria")
prevalencia_idade[,1] = c("0-9", "10-19", "20-29", "30-39", "40-49", "50-59", "60-69", "70-79", "80+")
names(prevalencia_idade)[2] = "Prevalencia"

#Fazer gráfico com faixa etária no eixo do x e prevalência no eixo do y
prevalencia_idade_grafico <- ggplot(prevalencia_idade, aes(x = Faixa_Etaria, y = Prevalencia)) +
  geom_col(fill = "coral2", width = 0.5, aes(text = paste('Faixa etária: ', Faixa_Etaria,
                                           '<br>Taxa de Incidência Cumulativa (%):', Prevalencia))) +
  scale_y_continuous(expand = c(0, 0)) +
  theme_classic() +
  labs(x = "") +
  theme(axis.text.x = element_text(size=8, color = "black"),
        axis.text.y = element_text(size=12, color = "black"))

#Tornar gráfico interativo
prevalencia_idade_grafico_interativo <- ggplotly(prevalencia_idade_grafico, tooltip = "text") %>% 
  layout(yaxis = list(title = paste0(c(rep("&nbsp;", 20),
                                      "Taxa de Incidência Cumulativa (%)",
                                       rep("&nbsp;", 20),
                                       rep("\n&nbsp;", 2)),
                                     collapse = "")))
#Prevalência por faixa etária diária

##Cálculo da prevalência
prevalencia_tempo_idade <- cbind(covid19pt$data, ((femininos + masculinos) / populacao_idades_pt_rep)*100)
names(prevalencia_tempo_idade) = c("Data", "0-9", "10-19", "20-29", "30-39", "40-49", "50-59", "60-69", "70-79", "80+")

##Fazer melt para fazer o gráfico
prevalencia_tempo_idade_melt <- melt(prevalencia_tempo_idade, id.vars = "Data")
names(prevalencia_tempo_idade_melt) = c("Data", "Faixa_Etaria", "Prevalencia")

##Fazer gráfico de linhas com data no eixo do x, prevalência no eixo do y e faixa etária nas cores das linhas
prevalencia_tempo_idade_grafico <- ggplot(prevalencia_tempo_idade_melt, aes(x = Data, y = Prevalencia, color = Faixa_Etaria)) +
  geom_line(size=0.5)+
  geom_point(size=0.1, aes(text = paste( 'Data: ', Data,
                                         '<br>Faixa Etária: ', Faixa_Etaria,
                                         '<br>Taxa de Incidência Cumulativa (%):', Prevalencia))) +
  labs(x = "") +
  theme(legend.title = element_blank(),
        axis.title.y = element_text(size = 12),
        axis.title.x = element_text(size = 12),
        legend.text = element_text(size = 8),
        axis.text.x = element_text(size = 6)) +
  scale_x_date(breaks = "3 months", date_labels = "%b %d")

##Tornar o grafico interativo
prevalencia_tempo_idade_grafico_interativo <- ggplotly(prevalencia_tempo_idade_grafico, tooltip = "text") %>% 
  layout(yaxis = list(title = paste0(c(rep("&nbsp;", 20),
                                       "Taxa de Incidência Cumulativa (%)",
                                       rep("&nbsp;", 20),
                                       rep("\n&nbsp;", 1)),
                                     collapse = "")),
         legend = list(x = 1, y = 0))

browsable(
  tagList(list(
    tags$div(
      style = 'width:50%;display:block;float:left;',
      prevalencia_idade_grafico_interativo
    ),
    tags$div(
      style = 'width:50%;display:block;float:left;',
      prevalencia_tempo_idade_grafico_interativo
    )
  ))
)

Evolução da Incidência por Género


Como podemos observar através deste gráfico, a incidência em ambos os géneros evoluiu de forma relativamente semelhante, sendo que o género feminino apresentou valores ligeiramente superiores. É provável que, nos meses iniciais da pandemia, indivíduos do sexo feminino tenham tido maior contacto direto com esta condição clínica, eventualmente pela profissão que exercem.

Mais uma vez, é de referir que esta análise não tem em consideração o número de indivíduos, tanto femininos como masculinos, no total da população.

#Duas tabelas com casos diários, uma para cada género
femininos_total_novos <- as.data.frame(covid19pt$confirmados_f - lag(covid19pt$confirmados_f))
masculinos_total_novos <- as.data.frame(covid19pt$confirmados_m - lag(covid19pt$confirmados_m))

#Juntar as tabelas e adicionar coluna com data
incidencia_genero <- cbind(covid19pt$data, femininos_total_novos, masculinos_total_novos)
names(incidencia_genero) = c("Data", "Feminino", "Masculino")

#Fazer melt para fazer o gráfico
incidencia_genero_melt <- melt(incidencia_genero, id.vars = "Data")
names(incidencia_genero_melt) = c("Data", "Genero", "Incidencia")

##Fazer gráfico de linhas com data no eixo do x, incidencia no eixo do y e género nas cores das linhas
incidencia_genero_grafico <- ggplot(incidencia_genero_melt, aes(x = Data, y = Incidencia, color = Genero)) +
  geom_line(size = 0.5) +
  geom_point(size = 0.1, aes(text = paste( 'Data: ', Data,
                                         '<br>Género: ', Genero,
                                         '<br>Incidência :', Incidencia))) +
  labs(x = "") +
  theme(legend.title = element_blank(),
        axis.text.x = element_text(size=8, color = "black"),
        axis.text.y = element_text(size=12, color = "black")) +
  scale_x_date(breaks = "3 months", date_labels = "%b %d")
  
#Tornar gráfico interativo
ggplotly(incidencia_genero_grafico, tooltip = "text" ) %>% 
  layout(yaxis = list(title = paste0(c(rep("&nbsp;", 20),
                                       "Incidência",
                                       rep("&nbsp;", 20),
                                       rep("\n&nbsp;", 2)),
                                     collapse = "")),
         legend = list(x = 1, y = 0))

Evolução da Taxa de Incidência por Género


Com a análise deste gráfico podemos verificar que não existem diferenças acentuadas entre os géneros, mesmo tendo em conta a proporção de indivíduos de cada género.

#Variáveis com a população total, feminina e masculina com base no INE
populacao_pt = 10295909
mulheres_pt = 5435932
homens_pt = 4859977

#Cálculo da incidência criando uma tabbela para o total, outra para mulheres e outra para homens
incidencia_total <- as.data.frame(covid19pt$confirmados_novos/ (populacao_pt - covid19pt$confirmados - covid19pt$obitos))
incidencia_homens <- as.data.frame((covid19pt$confirmados_m - lag(covid19pt$confirmados_m)) 
                                   / (homens_pt - covid19pt$confirmados_m)) 
incidencia_mulheres <- as.data.frame((covid19pt$confirmados_f - lag(covid19pt$confirmados_f)) 
                                     / (mulheres_pt - covid19pt$confirmados_f))

#Remover valores negativos devido a erro na base de dados original em que valor cumulativo do número casos homens e mulheres era 0 e não devia
incidencia_homens[174:175,] <- NA
incidencia_mulheres[174:175,] <- NA

#Criar uma tabela com as 3 tabelas anteriores, adicionando uma coluna com a data e mudar os nomes das colunas
incidencia <- data.frame(covid19pt$data, incidencia_total*100, incidencia_mulheres*100, incidencia_homens*100)
names(incidencia) <- c("Data", "Total", "Mulheres", "Homens")

#Fazer melt para poder fazer gráfico de linhas e dar nome à coluna do género
incidencia_melt <- melt(incidencia, id.vars = "Data")
names(incidencia_melt) <- c("Data", "Genero", "Incidencia")

#Fazer gráfico de linhas com data no eixo do x, a incidencia no eixo do y e o género em cada linha
ggplot(incidencia_melt, aes(x = Data, y = Incidencia, color = Genero)) +
  geom_point(size = 0.4) +
  geom_line(size = 0.4) +
  facet_grid(incidencia_melt$Genero) +
  theme(legend.position = "none") +
  labs(x = "", 
       y ="Taxa de Incidência (%)") +
  theme(axis.title.y = element_text(size = 12),
        axis.text.y = element_text(size = 8),
        strip.text.y = element_text(size = 8, angle = 0)) +
  scale_x_date(breaks = "3 months", date_labels = "%b %d")
      


Mortes


Neste tópico vamos abordar a mortalidade em valor absoluto (número de mortes), a taxa de mortalidade (número total de mortes/população total) e taxa de letalidade (número total de mortes/população infetada).


Mortalidade

Relação com a Evolução da Incidência


A evolução do número de mortes diárias tende a acompanhar a evolução do número de casos diários. Inicialmente, como os casos diagnosticados eram mais graves, os pacientes morriam mais cedo e por essa razão o desfasamento entre os casos e as mortes não era tão acentuado. Com a evolução da pandemia, começou a ser feito um diagnóstico mais precoce, o que aumentou o intervalo entre o diagnóstico e a morte.

De forma geral, o número de mortes diárias tem vindo a decrescer. À data da análise, podemos verificar que mesmo perante um grande aumento no número de casos diários, o número de mortes não tem acompanhado este aumento. Isto pode dever-se a um maior conhecimento sobre a doença, à maior incidência nas faixas etárias mais jovens e, talvez, uma menor virulência do vírus.

#Fazer tabela com coluna para data e outra para óbitos ocorridos em cada dia
mortes_diarias <- as.data.frame(cbind(covid19pt$data, as.data.frame(covid19pt$obitos - lag(covid19pt$obitos))))
names(mortes_diarias) = c("Data", "Mortes")

#Tabela com coluna para data, outra para casos e outra para mortes
casos_mortes_diarios <- merge(casos_diarios, mortes_diarias, by="Data")

#Fazer melt para poder fazer gráfico de linhas
casos_mortes_diarios_melt <- melt(casos_mortes_diarios, id.vars = "Data")

#Fazer gráfico de linhas com data no eixo do x, número no eixo do y e mortes ou casos em cada linha
ggplot(casos_mortes_diarios_melt, aes(x = Data, y = value, color = variable)) +
  geom_line(size = 1) +
  facet_grid(casos_mortes_diarios_melt$variable, scales = "free_y") +
  guides(color = FALSE) +
  labs(x = "", 
       y = "Número de Pessoas",
       color = "") +
  scale_color_discrete(labels = c("Incidência", "Mortes Diárias")) +
  theme(axis.title.x = element_text(margin = margin(t = 20, b = 20), 
                                    size = 12),
        axis.title.y = element_text(margin = margin(r = 20, l = 20), 
                                    size = 12)) +
  scale_x_date(breaks = "3 months", date_labels = "%b %d")

Por Faixa Etária e por Género


Neste gráfico de barras é facilmente visível que até aos 39 anos o número de mortes é quase inexistente. Começa a aumentar de forma mais significativa a partir dos 59 anos (o que confirma que se trata da população de risco), sendo a faixa etária dos 80+ anos aquela que tem, de longe, o maior número de mortes.

É perceptível também que o género masculino tem maior número de mortes, ao longo de todas as faixas etárias execto na faixa etária dos 80+. Para estes dados serem estatisticamente fiáveis, era necessário ter-se tido em conta a proporção de pessoas confirmadas dos géneros masculino e feminino existentes em cada faixa etária da população. No entanto, sabemos que em Portugal a esperança média de vida é superior nas mulheres do que nos homens, o que pressupõe que existem mais mulheres na faixa etária dos 80+ justificando, assim, um maior número de mortes do género feminino neste grupo etário.

#Selecionar as colunas de obitos feminino para todas as idades e juntá-las numa tabela e fazer o mesmo para o masculino
femininos_mortes <- as.data.frame(covid19pt %>% 
                                    dplyr::select(starts_with("obitos_") & (ends_with("9_f")| ends_with("plus_f"))))
masculinos_mortes <- as.data.frame(covid19pt %>% 
                                     dplyr::select((starts_with("obitos_") & (ends_with("9_m")| ends_with("plus_m")))))

#Selecionar o valor mais recente de cada coluna de modo a ficar com o número de óbitos até ao momento  para cada faixa etária e para cada género
mortes_femininos_idade <- as.data.frame(lapply(femininos_mortes, last))
mortes_masculinos_idade <- as.data.frame(lapply(masculinos_mortes, last))

#Criar tabela com uma colunda para a faixa etária e outra para o número de óbitos femininos e mudar coluna da  faixa etária para os nomes adequados
mortes_femininos_idade_invertido <- as.data.frame(t(mortes_femininos_idade))%>% 
  rownames_to_column(var = "Idade")
names(mortes_femininos_idade_invertido)[2] <- "Feminino"
mortes_femininos_idade_invertido[,1] <- c("0-9", "10-19", "20-29", "30-39", "40-49", "50-59", "60-69", "70-79", "80+")

#Criar tabela com uma colunda para a faixa etária e outra para o número de óbitos masculinos e mudar coluna da faixa etária para os nomes adequados
mortes_masculinos_idade_invertido <- as.data.frame(t(mortes_masculinos_idade)) %>% 
  rownames_to_column(var = "Idade")
names(mortes_masculinos_idade_invertido)[2] <- "Masculino"
mortes_masculinos_idade_invertido[,1] <- c("0-9", "10-19", "20-29", "30-39", "40-49", "50-59", "60-69", "70-79", "80+")

#Juntar as 3 tabelas que criámos
mortes_fem_masc <- merge(mortes_femininos_idade_invertido, mortes_masculinos_idade_invertido, by = "Idade")

#Fazer melt para poder fazer gráfico 
mortes_fem_masc_melt <- melt(mortes_fem_masc, id.vars = "Idade")
names(mortes_fem_masc_melt) = c("Idade", "Genero", "Mortes")

#Fazer gráfico de barras com idade no eixo do x, o número de óbitos no eixo do y e o género em cada barra
mortes_fem_masc_grafico <- ggplot(mortes_fem_masc_melt, aes(x = Idade, y = Mortes, fill = Genero)) +
  geom_col(position = "dodge", aes(text = paste( 'Faixa Etária: ', Idade,
                                         '<br>Género: ', Genero,
                                         '<br>Nº de mortes :', Mortes))) +
  scale_y_continuous(expand = c(0, 0)) +
  coord_cartesian( ylim = c(0, max(mortes_fem_masc_melt$Mortes + 100))) +
  theme_classic() +
  labs(x = "",
       y = "Mortes") +
  theme(legend.title = element_blank(),
        axis.title.x = element_text(size = 12),
        axis.text.x = element_text(size=8, color = "black"),
        axis.text.y = element_text(size=12, color = "black")) +
  guides(fill=guide_legend(title="género")) +
  scale_fill_manual(values = c("deeppink3", "lightblue", "grey60"))

#Tornar gráfico interativo
ggplotly(mortes_fem_masc_grafico, tooltip = "text") %>% 
  layout(yaxis = list(title = paste0(c(rep("&nbsp;", 20),
                                       "Número de Mortes",
                                       rep("&nbsp;", 20),
                                       rep("\n&nbsp;", 2)),
                                     collapse = "")),
         legend = list(x = 1, y = 0))

Por ARS


Neste gráfico de barras e no mapa vemos que a ARS com maior número de mortes é a Norte, seguida de Lisboa e Vale do Tejo. É importante realçar que este número é absoluto, logo, não tem em consideração a proporção de infetados de cada ARS.

#Criar tabela com uma coluna para as Regiãoes e outra para o número mais recente total de óbitos e dar nomes
mortos_regioes <- as.data.frame(t(as.data.frame(lapply(covid19pt[,obitos_arsnorte:obitos_madeira], last)))) %>% 
  rownames_to_column(var = "Regioes")
names(mortos_regioes)[2] <- "Mortes"
mortos_regioes[, 1] <- c("Norte", "Centro", "LVT", "Alentejo", "Algarve", "Açores", "Madeira")

#Fazer gráfico com Regiãoes no eixo do x e número de mortes no eixo do y
mortos_regioes_grafico <- ggplot(mortos_regioes, aes(x = Regioes, y = Mortes)) +
  geom_col(fill = "salmon1", width = 0.5, aes(text = paste( 'ARS: ', Regioes,
                                         '<br>Nº de mortes :', Mortes))) +
  scale_y_continuous(expand = c(0, 0)) +
  labs(x = "") +
  theme_classic() +
  theme(axis.title.y = element_text(size = 12))

mortos_regioes_grafico_interativo <- ggplotly(mortos_regioes_grafico, tooltip = "text") %>% 
  layout(yaxis = list(title = paste0(c(rep("&nbsp;", 20),
                                       "Número de Mortes",
                                       rep("&nbsp;", 20),
                                       rep("\n&nbsp;", 2)),
                                     collapse = "")))

#mapa
#Da tabela anterior com todas as datas, selecionar apenas o valor mais recente e mudar nome coluna e Regiãoes
incidencia_regioes_ordem <- as.data.frame(t(as.data.frame(lapply(incidencia_regioes[,c(5, 6, 7, 3, 8, 2, 4)], last)))) %>% 
  rownames_to_column(var = "Regiao") 
incidencia_regioes_ordem[,1] <- c("Alentejo", "Algarve", "Açores","Centro", "Madeira", "Norte", "Lisboa e Vale do Tejo")

##Definir intervalos da legenda
bins_3 =  c(0, 25, 50, 100, 500, 1000, Inf)

##Ordenar a tabela feita anteriormente para ficar com a mesma ordem que os poligonos do mapa
mortos_regioes_ordem <- mortos_regioes[c(4, 5, 6, 2, 7, 1, 3),]

##Definir a palete de cores
pal_3 <- colorBin("YlOrRd", domain = mortos_regioes_ordem[,2], bins = bins_3)

##Definir a legenda quando se passa com o rato por cima
labels_3 <- sprintf(
  "<strong>%s</strong><br/>%g Mortos",
  incidencia_regioes_ordem[,1], mortos_regioes_ordem[,2]
) %>% lapply(htmltools::HTML)

##Fazer o mapa
mortos_regioes_mapa <- leaflet(mapa_pt) %>% 
  addTiles(group = "Normal") %>% 
  addProviderTiles(providers$CartoDB.Positron, group = "Claro") %>% 
  addProviderTiles(providers$CartoDB.DarkMatterNoLabels, group = "Escuro") %>% 
  addLayersControl(
    baseGroups = c("Normal", "Claro", "Escuro"),
    options = layersControlOptions(collapsed = TRUE)
  ) %>% 
  addPolygons(
    fillColor = ~pal_3(mortos_regioes_ordem[,2]), 
    weight = 2,
    opacity = 1,
    color = "white",
    dashArray = "3",
    fillOpacity = 0.7,
    highlight = highlightOptions(
      weight = 5,
      color = "#666",
      dashArray = "",
      fillOpacity = 0.7,
      bringToFront = TRUE),
    label = labels_3,
    labelOptions = labelOptions(style = list("font-weight" = "normal", 
                                             padding = "3px 8px"),
                                textsize = "15px",
                                direction = "auto")) %>% 
  addLegend(pal = pal_3, values = incidencia_regioes_ordem[,2], opacity = 0.7, title = "Número de Mortes por ARS",
            position = "bottomright")

browsable(
  tagList(list(
    tags$div(
      style = 'width:50%;display:block;float:left;',
      mortos_regioes_mapa
    ),
    tags$div(
      style = 'width:50%;display:block;float:left;',
      mortos_regioes_grafico_interativo
    )
  ))
)

Taxa de Mortalidade

Por Género


Neste gráfico de barras podemos ver que os homens têm uma taxa de mortalidade superior à das mulheres. Contudo, este gráfico não tem em conta se existem mais pessoas do género masculino infetadas do que do género feminino.

#Cálculo da mortalidade total, feminina e masculina com base no valor mais recente dos óbitos, que é também o mais alto
mortalidade_total <- max(covid19pt$obitos, na.rm = TRUE) / populacao_pt
mortalidade_mulheres <- max(covid19pt$obitos_f, na.rm = TRUE) / mulheres_pt
mortalidade_homens <- max(covid19pt$obitos_m, na.rm =TRUE) / homens_pt

#Criar uma tabela com uma coluna para o género e outra para o valor da mortalidade e dar nome apropriado aos generos
mortalidade <- data.frame(t(data.frame(mortalidade_total, mortalidade_mulheres, mortalidade_homens))) %>% 
  rownames_to_column(var = "genero")
names(mortalidade)[2] <- "mortalidade"
mortalidade[, 1] <- c("Total", "Mulheres", "Homens")

#Criar um gráfico de barras com o genero no eixo do x e a mortalidade no eixo do y
ggplot(mortalidade, aes(x = genero, y = mortalidade*100)) +
  geom_col(fill = "salmon1", width = 0.5) +
  coord_cartesian( ylim = c(0, max(mortalidade$mortalidade*106))) +
  scale_y_continuous(expand = c(0, 0)) +
  theme_classic() +
  labs(x = "",
       y = "Taxa de Mortalidade (%)") +
  theme(axis.title.x = element_text(margin = margin(t = 20, b = 20), 
                                    size = 12),
        axis.title.y = element_text(margin = margin(r = 20, l = 20), 
                                    size = 12),
        axis.text.x = element_text(size=12, color = "black"),
        axis.text.y = element_text(size=12, color = "black")) +
  geom_text(aes(label = scales::percent(mortalidade, digits = 4)), 
            vjust = -0.5, 
            size = 4)

Por Faixa Etária

Neste gráfico de barras é possível verificar que a taxa de mortalidade aumenta com o aumento da idade. Isto demonstra, mais uma vez, que a idade é um importante fator de risco, especialmente para a faixa etária dos 80+ anos.

#Calcular a taxa de mortalidade para cada faixa etária e adicionar coluna com faixas etárias
mortalidade_idade <- cbind(mortes_femininos_idade_invertido[,1], ((mortes_femininos_idade_invertido[,2] 
                                                                   + mortes_masculinos_idade_invertido[,2])*100/ populacao_idades_pt))
names(mortalidade_idade) = c("Faixa_Etaria", "Taxa_Mortalidade")

#Fazer o gráfico com faixa etária no eixo do x e taxa de mortalidade no eixo do y
mortalidade_idade_grafico <- ggplot(mortalidade_idade, aes(x = Faixa_Etaria, y = Taxa_Mortalidade)) +
  geom_col(fill = "salmon1", width = 0.5, aes(text = paste( 'Faixa Etária: ', Faixa_Etaria,
                                         '<br>Taxa de Mortalidade (%) :', Taxa_Mortalidade))) +
  scale_y_continuous(expand = c(0, 0)) +
  theme_classic() +
  labs(x = "") +
  theme(axis.title.y = element_text(margin = margin(r = 20, l = 20), 
                                    size = 12),
        axis.text.x = element_text(size=12, color = "black"),
        axis.text.y = element_text(size=12, color = "black"))

#Tornar gráfico interativo
ggplotly(mortalidade_idade_grafico, tooltip = "text") %>% 
  layout(yaxis = list(title = paste0(c(rep("&nbsp;", 20),
                                     "Taxa de Mortalidade (%)",
                                     rep("&nbsp;", 20),
                                     rep("\n&nbsp;", 2)),
                                   collapse = "")))

Por ARS


Neste gráfico de barras e mapa, é possível ver que a ARS Lisboa e Vale do Tejo é a que tem a maior taxa de mortalidade seguida da ARS Norte. Por outro lado, é notável o facto de a Madeira ainda não apresentar qualquer caso de morte pela COVID-19.

#Criar tabela com uma coluna para as Regiãoes e outra para a mortalidade mais recente e dar nomes apropriados
mortalidade_regioes <- data.frame(t(as.data.frame(lapply(covid19pt[, obitos_arsnorte:obitos_madeira], last)) *100) 
                                  / populacao_regioes) %>% 
  rownames_to_column(var = "Regiao")
names(mortalidade_regioes)[2] <- "Mortalidade"
mortalidade_regioes[, 1] <- c("Norte", "Centro", "LVT", "Alentejo", "Algarve", "Açores", "Madeira")

#Fazer gráfico com Regiãoes no eixo do x e mortaldiade no eixo do y
mortalidade_regioes_grafico <- ggplot(mortalidade_regioes, aes(x = Regiao, y = Mortalidade)) +
  geom_col(fill = "gray", width = 0.5, aes(text = paste( 'ARS: ', Regiao,
                                         '<br>Taxa de Mortalidade (%) :', Mortalidade))) +
  scale_y_continuous(expand = c(0, 0)) +
  theme_classic() +
  labs(x="") +
  theme(axis.text.y = element_text(size=12))
mortalidade_regioes_grafico_interativo <- ggplotly(mortalidade_regioes_grafico, tooltip = "text") %>% 
  layout(yaxis = list(title = paste0(c(rep("&nbsp;", 20),
                                     "Taxa de Mortalidade (%)",
                                     rep("&nbsp;", 20),
                                     rep("\n&nbsp;", 2)),
                                   collapse = "")))
#mapa
##Definir intervalos da legenda
bins_4 =  c(0, 0.006, 0.001, 0.015, 0.02, 0.025, 0.03, Inf)

##Ordenar a tabela feita anteriormente para ficar com a mesma ordem que os poligonos do mapa
mortalidade_regioes_ordem <- mortalidade_regioes[c(4, 5, 6, 2, 7, 1, 3),]

####Definir a palete de cores
pal_4 <- colorBin("YlOrRd", domain = mortalidade_regioes_ordem[,2], bins = bins_4)

##Definir a legenda quando se passa com o rato por cima
labels_4 <- sprintf(
  "<strong>%s</strong><br/>%g&#x25 Mortalidade",
  mortalidade_regioes_ordem[,1], round(mortalidade_regioes_ordem[,2], digits =  3)
) %>% lapply(htmltools::HTML)

##Fazer o map
mortalidade_regioes_mapa <- leaflet(mapa_pt) %>% 
  addTiles(group = "Normal") %>% 
  addProviderTiles(providers$CartoDB.Positron, group = "Claro") %>% 
  addProviderTiles(providers$CartoDB.DarkMatterNoLabels, group = "Escuro") %>% 
  addLayersControl(
    baseGroups = c("Normal", "Claro", "Escuro"),
    options = layersControlOptions(collapsed = TRUE)
  ) %>% 
  addPolygons(
    fillColor = ~pal_4(mortalidade_regioes_ordem[,2]), 
    weight = 2,
    opacity = 1,
    color = "white",
    dashArray = "3",
    fillOpacity = 0.7,
    highlight = highlightOptions(
      weight = 5,
      color = "#666",
      dashArray = "",
      fillOpacity = 0.7,
      bringToFront = TRUE),
    label = labels_4,
    labelOptions = labelOptions(style = list("font-weight" = "normal", 
                                             padding = "3px 8px"),
                                textsize = "15px",
                                direction = "auto")) %>% 
  addLegend(pal = pal_4, values = mortalidade_regioes_ordem[,2], opacity = 0.7, title = "Taxa de Mortalidade (%) por ARS",
            position = "bottomright")

browsable(
  tagList(list(
    tags$div(
      style = 'width:50%;display:block;float:left;',
      mortalidade_regioes_mapa
    ),
    tags$div(
      style = 'width:50%;display:block;float:left;',
      mortalidade_regioes_grafico_interativo
    )
  ))
)

Taxa de Letalidade

Por Género


Com a análise deste gráfico de barras é possível concluir que os homens afetados com COVID-19 tem uma maior probabilidade de morrer, relativamente às mulheres infetadas. Isto pode ser justificado pelo estilo de vida menos saudável adotado por este género (maior percentagem de tabagismo e alcoolismo).

#Cálculo da letalidade total, feminina e masculina com base no valor mais recente dos óbitos,  que é também o mais alto, e no valor mais recente de confirmados
letalidade_total <- max(covid19pt$obitos, na.rm = TRUE) / last(covid19pt$confirmados)
letalidade_mulheres <- max(covid19pt$obitos_f, na.rm = TRUE) / last(covid19pt$confirmados_f)
letalidade_homens <- max(covid19pt$obitos_m, na.rm = TRUE) / last(covid19pt$confirmados_m)

#Criar uma tabela com uma coluna para o género e outra para o valor da letalidade e dar nome apropriado aos generos
letalidade <- data.frame(t(data.frame(letalidade_total, letalidade_mulheres, letalidade_homens))) %>% 
  rownames_to_column(var = "genero")
names(letalidade)[2] <- "letalidade"
letalidade[, 1] <- c("Total", "Mulheres", "Homens")

#Criar um gráfico de barras com o genero no eixo do x e a letalidade no eixo do y
ggplot(letalidade, aes(x = genero, y = letalidade*100)) +
  geom_col(fill = "salmon1", width = 0.5) +
  scale_y_continuous(expand = c(0, 0)) +
  coord_cartesian( ylim = c(0, max(letalidade$letalidade*100 + 1))) +
  theme_classic() +
  labs(x = "",
       y = "Taxa de Letalidade(%)") +
  theme(axis.title.x = element_text(margin = margin(t = 20, b = 20), 
                                    size = 15),
        axis.title.y = element_text(margin = margin(r = 20, l = 20), 
                                    size = 15),
        axis.text.x = element_text(size=12, 
                                   color = "black"),
        axis.text.y = element_text(size=12, color = "black")) +
  geom_text(aes(label = scales::percent(letalidade, digits = 4)), 
            vjust = -0.5, 
            size = 4)

Evolução por Género


No gráfico de linhas podemos ver que, a partir de meados de março, a letalidade sofreu um aumento considerável uma vez que os mais velhos, população mais debilitada, eram dos grupos etários mais afetados, atingindo o seu pico no dia 05/05/2020 com 5.04%. A partir de junho, a letalidade tem vindo a diminuir. Uma das razões que pode explicar este facto é a faixa etária da população infetada, que se alterou, passando dos mais velhos para os mais jovens, que têm menor probabilidade de morrer da doença viral. Para além deste motivo, existem ainda outros fatores a considerar, nomeadamente um maior conhecimento e experiência por parte dos profissionais de saúde, um alargamento do número de testes realizados e ainda uma melhoria da capacidade de resposta do sistema de saúde.

#Calcular letalidade toal, para mulheres e para homens, criando uma tabela para cada com uma coluna para a  data e outra para os valores da letalidade para cada dia
letalidade_tempo_total <- cbind(covid19pt$data, as.data.frame((covid19pt$obitos / covid19pt$confirmados)*100))
letalidade_tempo_mulheres <- cbind(covid19pt$data, as.data.frame((covid19pt$obitos_f / covid19pt$confirmados_f)*100))
letalidade_tempo_homens <- cbind(covid19pt$data, as.data.frame((covid19pt$obitos_m / covid19pt$confirmados_m)*100))

#Juntar as 3 tabelas numa são mudando os nomes de cada coluna
letalidade_tempo_total_mulheres <- merge(letalidade_tempo_total, letalidade_tempo_mulheres, by ="covid19pt$data")
letalidade_tempo <- merge(letalidade_tempo_total_mulheres, letalidade_tempo_homens, by="covid19pt$data")
names(letalidade_tempo) <- c("Data", "Total", "Feminino", "Masculino")

#Fazer o melt para poder faze um gráfico de linhas
letalidade_tempo_melt <- melt(letalidade_tempo, id.vars = "Data")
names(letalidade_tempo_melt) <- c("Data", "Genero", "Letalidade")

#Fazer gráfico de linhas com a data no eixo do x, a letalidade no eixo do y e o género em cada linha
letalidade_tempo_grafico <- ggplot(letalidade_tempo_melt, aes(x = Data, y = Letalidade, color = Genero)) +
  geom_line(size=0.5) +
  geom_point(size=0.1, aes(text = paste( 'Data: ', Data,
                                         '<br>Género :', Genero,
                                         '<br>Taxa de Letalidade (%) :', Letalidade ))) +
  labs(x = "",
       y = "Taxa de Letalidade (%)") +
  theme(legend.title = element_blank(),
        axis.title.x = element_text(size = 12),
        axis.title.y = element_text(size = 12))+
  scale_x_date(breaks = "3 months", date_labels = "%b %d")

#Tornar gráfico interativo
ggplotly(letalidade_tempo_grafico, add_tracey = "Taxa de Letalidade (%)", tooltip = "text") %>% 
  layout(legend = list(x = 1, y = 0))

Por Faixa Etária e Género


Pela análise do gráfico de pontos, é possível ver que as faixas etárias entre os 0 e os 49 anos não apresentam diferenças significativas nos valores da letalidade entre si, e o mesmo acontece para os géneros dentro de cada faixa etária.

Os homens tendem a apresentar uma taxa de letalidade superior a partir da faixa etária dos 50 aos 59 anos, que se vai acentuando com a idade, o que, de acordo com estudos recentes, pode estar relacionado com a pré-existência de maior número de co-morbilidades, com um maior consumo de bebidas alcoólicas e maior tendência para o tabagismo, diferenças na resposta imunitária, questões fisiológicas relacionadas com o recetor ACE2 viral (que pode ter uma expressão diferente entre géneros) e, ainda, diferenças comportamentais, nomeadamente uma menor tendência para recorrer a serviços médicos.

É ainda relevante mencionar que a taxa de letalidade aumenta com o aumento da idade. Pode dever-se ao facto de serem faixas etárias mais debilitadas e, normalmente, com maior número de doenças concomitantes. Isto é particularmente notório na faixa etária dos 80+.

#Criar tabela com uma colunda para a faixa etária e outra para o número de casos total e mudar coluna da faixa etária para os nomes adequados
casos_total_idade_invertido <- as.data.frame(t(casos_total_idade)) %>% 
  rownames_to_column(var = "Idade")
names(casos_total_idade_invertido)[2] <- "Total"
casos_total_idade_invertido[,1] <- c("0-9", "10-19", "20-29", "30-39", "40-49", "50-59", "60-69", "70-79", "80+")

#Tabela com número de casos confirmados por faixa etária por género
casos_genero_idade <- merge(casos_femininos_idade_invertido, casos_masculinos_idade_invertido, by = "Idade")
casos_genero_idade_total <-  merge(casos_genero_idade, casos_total_idade_invertido, by = "Idade")

#Somar a tabela dos femininos com a dos masculinos o que vai dar o número de óbitos até ao momento por idade apenas
mortes_total_idade <- as.data.frame(mortes_femininos_idade + mortes_masculinos_idade)

#Criar tabela com uma colunda para a faixa etária e outra para o número de óbitos total e mudar coluna da faixa etária para os nomes adequados
mortes_total_idade_invertido <- as.data.frame(t(mortes_total_idade)) %>% 
  rownames_to_column(var = "Idade")
names(mortes_total_idade_invertido)[2] <- "Total"
mortes_total_idade_invertido[,1] <- c("0-9", "10-19", "20-29", "30-39", "40-49", "50-59", "60-69", "70-79", "80+")

#Tabela com número de óbitos por faixa etária por género
mortes_genero_idade <- merge(mortes_femininos_idade_invertido, mortes_masculinos_idade_invertido, by = "Idade")
mortes_genero_idade_total <-  merge(mortes_genero_idade, mortes_total_idade_invertido, by = "Idade")

#Criar tabela com uma coluna com as faixas etárioas e outra com a letalidade e dar nomes às colunas
letalidade_genero_idade <- cbind(casos_femininos_idade_invertido[,1], (mortes_genero_idade_total[,2:4]/casos_genero_idade_total[,2:4]))
names(letalidade_genero_idade) <- c("Idade", "Feminino", "Masculino", "Total")

#Fazer melt para poder fazer gráfico
letalidade_genero_idade_melt <- melt(letalidade_genero_idade, id.vars = "Idade")

#Fazer gráfico com idade no eixo do x, letalidade no eixo do y e faixa etária em cada linha
letalidade_genero_idade_grafico <- ggplot(letalidade_genero_idade_melt, aes(x = Idade, y = value*100, color = variable, 
                                                                tooltip = round(value*100, digits = 2), data_id = value)) +
  geom_point_interactive() +
  labs(x ="",
       y = "Taxa de Letalidade (%)") +
  theme(axis.title.x = element_text(margin = margin(t = 20, b = 20,), 
                                    size = 12),
        axis.title.y = element_text(margin = margin(r = 20, l = 20), 
                                    size = 12)) +
  scale_color_discrete(name= "Genéro")
        
#Animar o gráfico 
girafe(code = print(letalidade_genero_idade_grafico),
       options = list(
         opts_zoom(max = 2),
         opts_hover(css = "fill:black;"),
         opts_sizing(rescale = TRUE, width = 0.8)
       ))

Evolução por Faixa Etária


Neste gráfico de linhas podemos verificar que nas faixas etárias entre os 0 e os 59 anos, a taxa de letalidade tem-se mantido relativamente constante e baixa, uma vez que não constituem a fração da população de maior risco.

Relativamente às faixas etárias entre os 60 e os 80+ (faixas etárias de risco), a taxa de letalidade foi aumentando progressivamente até junho dada a falta de conhecimento inicial desta doença viral e a ocorrência de surtos em lares. Posteriormente, as taxas de letalidade têm vindo a diminuir pois, para além de um maior conhecimento, existe uma melhor capacidade de resposta médica. No entanto, prevemos um aumento destas taxas devido ao recente aumento no número de casos nestas faixas etárias.

#Tabela com o número de mortes total diários por faixa etária
total_mortes_novos <- femininos_mortes + masculinos_mortes

#Tabela com o número de casos totais diários por faixa etária
total_casos_novos <- femininos + masculinos

#Tabela com uma coluna com a data e outras com cada faixa etária onde tem o valor da letalidade total para cada dia e  dar nomes às colunas
letalidade_tempo_idade <- cbind(covid19pt$data, total_mortes_novos/total_casos_novos)
names(letalidade_tempo_idade) <- c("Data", "0-9", "10-19", "20-29", "30-39", "40-49", "50-59", "60-69", "70-79", "80+")

#Fazer melt para fazer o gráfico
letalidade_tempo_idade_melt <- melt(letalidade_tempo_idade, id.vars = "Data")

#Fazer o gráfico
letalidade_tempo_idade_grafico <- ggplot(letalidade_tempo_idade_melt, aes(x = Data, y = value*100, color = variable)) +
  geom_line(size = 0.5) +
  geom_point(size=0.1, aes(text = paste( 'Data: ', Data,
                                         '<br>Faixa Etária :', variable,
                                         '<br>Taxa de Letalidade (%) :', value*100 ))) +
  labs(x ="",
       y = "Taxa de Letalidade (%)") +
  theme(axis.title.x = element_text(margin = margin(t = 20 ,b = 20), 
                                    size = 15),
        axis.title.y = element_text(margin = margin(r = 20, l = 20), 
                                    size = 15),
        strip.text.y = element_text(angle = 0),
        legend.title = element_blank()) +
  scale_x_date(breaks = "3 months", date_labels = "%b %d")

#Tornar o gráfico interativo
ggplotly(letalidade_tempo_idade_grafico, tooltip = "text")

Por ARS


Ao interpretarmos este gráfico de barras e este mapa, verificamos que os Açores têm uma taxa de letalidade muito elevada o que pode dever-se a uma débil estrutura médica e/ou uma maior incidência na população mais envelhecida. O mesmo também se verifica na ARS do Centro, ainda que com uma taxa de letalidade ligeiramente menor, que, às razões anteriormente mencionadas, pode-se acrescentar o facto de existir uma elevada discrepância de acessibilidade aos serviços hospitalares entre os concelhos do litoral e do interior.

Relativamente à ARS do Norte, esta apresenta a terceira taxa de letalidade mais elevada, provavelmente resultante dos primeiros surtos em Portugal terem ocorrido nesta ARS.

Nas ARSs do Algarve e do Alentejo, era de esperar que as taxas de letalidade fossem mais elevadas. No entanto isto não se verifica, possivelmente pelo facto de terem sido atingidas faixas etárias mais jovens que estabelecem mais contacto entre si, enquanto que as faixas etárias mais velhas se encontram em zonas rurais e, por isso, mais isoladas.

A taxa de letalidade na ARS de Lisboa e Vale do Tejo parece ser baixa dada a prevalência que existe nesta ARS. Isto demonstra que possui um serviço de saúde eficaz com uma boa resposta médica.

Na Madeira a taxa de letalidade é zero, uma vez que não se verificaram óbitos nesta região. Este valor pode dever-se, por um lado à qualidade do serviço médico prestado ou, por outro lado, a uma menor incidência nas faixas etárias com maior risco de morte.

#Fazer uma tabela com uma coluna com a Região e outra com a letalidade para cada Região e dar nomes adequados
letalidade_regioes <- data.frame(t(as.data.frame(lapply(covid19pt[, obitos_arsnorte:obitos_madeira], last))*100 
                                   / (as.data.frame(lapply(covid19pt[, confirmados_arsnorte:confirmados_madeira], last))))) %>% 
  rownames_to_column(var = "Regiao")
names(letalidade_regioes)[2] <- "Letalidade"
letalidade_regioes[, 1] <- c("Norte", "Centro", "LVT", "Alentejo", "Algarve", "Açores", "Madeira")

#Fazer o gráfico com a Região no eixo do x e a letalidade no eixo do y
letalidade_regioes_grafico <- ggplot(letalidade_regioes, aes(x = Regiao, y = Letalidade)) +
  geom_col(fill = "gray", width = 0.5, aes(text = paste( 'ARS: ', Regiao,
                                         '<br>Taxa de Letalidade (%) :', Letalidade))) +
  scale_y_continuous(expand = c(0, 0)) +
  theme_classic() +
  labs(x = "") +
  theme(axis.text.y = element_text(size=12))

letalidade_regioes_grafico_interativo <- ggplotly(letalidade_regioes_grafico, tooltip = "text") %>% 
  layout(yaxis = list(title = paste0(c(rep("&nbsp;", 20),
                                     "Taxa de Letalidade (%)",
                                     rep("&nbsp;", 20),
                                     rep("\n&nbsp;", 2)),
                                   collapse = "")))
#mapa
##Definir intervalos da legenda
bins_5 =  c(0, 1, 2, 3, 4, 5, Inf)

##Ordenar a tabela feita anteriormente para ficar com a mesma ordem que os poligonos do mapa
letalidade_regioes_ordem <- letalidade_regioes[c(4, 5, 6, 2, 7, 1, 3),]

##Definir a palete de cores
pal_5 <- colorBin("YlOrRd", domain = letalidade_regioes_ordem[,2], bins = bins_5)

##Definir a legenda quando se passa com o rato por cima
labels_5 <- sprintf(
  "<strong>%s</strong><br/>%g&#x25 Letalidade",
  letalidade_regioes_ordem[,1], round(letalidade_regioes_ordem[,2], digits =  2)
) %>% lapply(htmltools::HTML)

##Fazer o mapa
letalidade_regioes_mapa <- leaflet(mapa_pt) %>% 
  addTiles(group = "Normal") %>% 
  addProviderTiles(providers$CartoDB.Positron, group = "Claro") %>% 
  addProviderTiles(providers$CartoDB.DarkMatterNoLabels, group = "Escuro") %>% 
  addLayersControl(
    baseGroups = c("Normal", "Claro", "Escuro"),
    options = layersControlOptions(collapsed = TRUE)
  ) %>% 
  addPolygons(
    fillColor = ~pal_5(letalidade_regioes_ordem[,2]), 
    weight = 2,
    opacity = 1,
    color = "white",
    dashArray = "3",
    fillOpacity = 0.7,
    highlight = highlightOptions(
      weight = 5,
      color = "#666",
      dashArray = "",
      fillOpacity = 0.7,
      bringToFront = TRUE),
    label = labels_5,
    labelOptions = labelOptions(style = list("font-weight" = "normal", 
                                             padding = "3px 8px"),
                                textsize = "15px",
                                direction = "auto")) %>% 
  addLegend(pal = pal_5, values = letalidade_regioes_ordem[,2], opacity = 0.7, title = "Taxa de Letalidade (%) por ARS",
            position = "bottomright")

browsable(
  tagList(list(
    tags$div(
      style = 'width:50%;display:block;float:left;',
      letalidade_regioes_mapa
    ),
    tags$div(
      style = 'width:50%;display:block;float:left;',
      letalidade_regioes_grafico_interativo
    )
  ))
)

Evolução por ARS


Segundo este gráfico de linhas, podemos ver que as ARSs do Norte, do Centro, de Lisboa e Vale do Tejo e do Algarve apresentam um comportamento semelhante embora em diferentes proporções, com os valores máximos entre maio e junho. A partir de junho os valores têm vindo a decrescer pelas razões mencionadas anteriormente, especialmente a ARS do Algarve em que essa diminuição foi mais acentuada, eventualmente devido à maior incidência em indivíduos mais jovens.

No caso dos Açores ocorreu um aumento abrupto da taxa de letalidade, em que no seu pico cerca de 11% das pessoas infetadas morriam. Desde junho esta taxa tem vindo a diminuir, possivelmente devido à estratégia implementada da realização de uma testagem em grande escala, detetando assim os casos assintomáticos e menos graves.

A ARS do Alentejo apresenta um comportamento atípico. Ocorre um pico no dia 03/04/2020 que pode representar a morte de pessoas infetadas no início da pandemia, no entanto é invulgar que tenham todas ocorrido no mesmo dia. De seguida a taxa de letalidade regressa a 0%, o que demonstra que houve um lapso no registo dos óbitos. Entre maio e junho a taxa de letalidade manteve-se em platô, sendo isso também incomum. De seguida, apresentou um aumento abrupto que pode ser explicado pelo aumento da incidência, possivelmente em faixas etárias mais velhas. Desde julho, tem demonstrado um comportamento semelhante às outras ARSs, com uma descida da taxa de letalidade.

Na Madeira a taxa de letalidade é zero, uma vez que não se verificaram óbitos nesta região.

#Criar tabela com uma coluna para data e outras colunas uma para cada região tendo lá os valores da letalidade diária e dar nomes às colunas
letalidade_regioes_tempo <- cbind(covid19pt$data, as.data.frame((covid19pt[,49:55]/covid19pt[,4:10]))*100)
names(letalidade_regioes_tempo) <- c("Data", "Norte", "Centro", "Lisboa e Vale do Tejo", "Alentejo", 
                                     "Algarve", "Açores", "Madeira")

#Fazer melt para poder fazer o gráfico
letalidade_regioes_tempo_melt <- melt(letalidade_regioes_tempo, id.vars = "Data")
names(letalidade_regioes_tempo_melt) = c("Data", "Regiao", "Letalidade")

#Fazer o gráfico de linhas com data no eixo do x, letalidade no eixo do y e regiao em cada linha
letalidade_regioes_tempo_grafico <- ggplot(letalidade_regioes_tempo_melt, aes(x = Data, y = Letalidade, 
                                                                              color = Regiao)) +
  geom_line(size=0.5) +
  geom_point(size=0.1, aes(text = paste( 'Data: ', Data,
                                         '<br>ARS :', Regiao,
                                         '<br>Taxa de Letalidade (%) :', Letalidade ))) +
  labs(x = "",
       y ="Letalidade (%)") +
  theme(legend.title = element_blank(),
        axis.title.y = element_text(size = 12),
        axis.title.x = element_text(size = 12),
        legend.text = element_text(size = 8),
        axis.text.x = element_text(size = 8)) +
  scale_x_date(breaks = "3 months", date_labels = "%b %d")

#Tornar gráfico interativo
ggplotly(letalidade_regioes_tempo_grafico, tooltip = "text") %>% 
  layout(yaxis = list(title = paste0(c(rep("&nbsp;", 20),
                                       "Taxa de Letalidade (%)",
                                       rep("&nbsp;", 20),
                                       rep("\n&nbsp;", 2)),
                                     collapse = "")),
         legend = list(x = 1, y = 0))

Internamentos


Um fator muito importante a ter em conta no decorrer de uma pandemia é, não só o número de pessoas infetadas, mas também o número de pessoas que necessita de acompanhamento hospitalar para impedir a falência do sistema de saúde.


Evolução do Número de Internados


Ao realizar a interpretação deste gráfico verificámos que no início da pandemia o número de internados aumentou exponencialmente, tendo atingido o valor máximo no dia 16/04/2020. É de salientar que nesta fase ainda não existia o conhecimento necessário para atuar medicamente sobre os casos mais graves da doença e, também por essa falta de conhecimento, recorria-se a um internamento mais precoce. Para além disso, uma das faixas etárias mais atingidas foi a dos 80+ anos, levando, naturalmente, a um maior número de complicações. Desde esse pico até meados de junho, o número de internados foi diminuindo, seguindo-se um ligeiro aumento até julho com nova descida até setembro. A partir de setembro o número de internados tem vindo a acompanhar o aumento no número de casos.

Relativamenta aos internados na unidade de cuidados intensivos (UCI), houve um aumento concordante com o aumento dos internados, embora em muito menor escala. A partir do dia 7/04/2020 foi diminuindo gradualmente tendo voltado a aumentar também no início de setembro.

#Fazer melt das colunas data, internados e internados UCI para ter número de internados em cada dia
internados <- melt(covid19pt[,c(1, 15, 88, 16)], id.vars = "data")

#Mudar o nome do conteúdo da coluna dos internados para internados ou internados UCI
levels(internados$variable)[levels(internados$variable)=="internados"] <- "Internados Total"
levels(internados$variable)[levels(internados$variable)=="internados_uci"] <- "Internados UCI"
levels(internados$variable)[levels(internados$variable)=="internados_enfermaria"] <- "Internados Enfermaria"
names(internados) = c("data", "tipo_internamento", "internados")

#Fazer gráfico de linhas com data no eixo do x, número de internados no eixo do y e tipo de internamento nas linhas
internados_grafico <- ggplot(internados, aes(x = data, y =internados, color = tipo_internamento)) +
  geom_line(size = 0.5) +
  geom_point(size=0.1, aes(text = paste( 'Data: ', data,
                                         '<br>Tipo de Internamento :', tipo_internamento,
                                         '<br>Nº de Internados :', internados ))) +
  labs(x = "", color = "") +
  theme(axis.title.y = element_text(size = 12),
        axis.title.x = element_text(size = 12),
        axis.text.x = element_text(size = 7)) +
  scale_x_date(breaks = "3 months", date_labels = "%b %d")

#Tornar gráfico interativo
ggplotly(internados_grafico, tooltip = "text") %>% 
  layout(yaxis = list(title = paste0(c(rep("&nbsp;", 20),
                                       "Número de Internados",
                                       rep("&nbsp;", 20),
                                       rep("\n&nbsp;", 2)),
                                     collapse = "")),
         legend = list(x = 1, y = 0))

Evolução da Taxa de Internamento


No início da pandemia apenas os casos graves procuravam ajuda médica e, por isso, eram os únicos a serem diagnosticados, o que justifica a taxa de internamento de 100%. De seguida houve uma descida abrupta, explicada pelo aumento do diagnóstico de casos menos graves. No final de março houve um ligeiro aumento na taxa de internados. Posteriormente houve uma diminuição desta taxa, possivelmente devido a um maior conhecimento desta condição médica assim como uma maior incidência nas faixas etárias mais jovens. A partir de setembro a taxa apresenta um comportamento ligeiramente crescente, que pode dever-se a um novo aumento do número de casos nas faixas etárias mais velhas (gráfico da Evolução da Incidência por Faixa Etária).

#Fazer melt para ter tabela com coluna da data, coluna do tipo de internamento e coluna com percentagem de internados que são os internados a dividir pelos confirmados e dar nomes às colunas
internados_confirmados <- melt((cbind(covid19pt$data, (as.data.frame(lapply(covid19pt[,c(15, 88, 16)], 
                                                                       function(x) {(x/covid19pt[, 3])*100}))))), id.vars = "covid19pt$data")
names(internados_confirmados) <- c("data", "internados", "percentagem")

#Mudar o nome do conteúdo da coluna dos internados para internados ou internados UCI
levels(internados_confirmados$internados)[levels(internados_confirmados$internados)=="confirmados"] <- " Internados Total"
levels(internados_confirmados$internados)[levels(internados_confirmados$internados)=="confirmados.1"] <- "Internados Enfermaria"
levels(internados_confirmados$internados)[levels(internados_confirmados$internados)=="confirmados.2"] <- "Internados UCI"

#Fazer gráfico de linhas com data no eixo do x, percentagem internados no eixo do y e tipo de internamento em cada linha
internados_confirmados_grafico <- ggplot(internados_confirmados, aes(x = data, y = percentagem, color = internados)) +
  geom_line(size = 0.5) +
  geom_point(size=0.1, aes(text = paste( 'Data: ', data,
                                         '<br>Tipo de Internamento :', internados,
                                         '<br>Taxa de Internamento (%) :', percentagem ))) +
  labs(x = "", color = "") +
  theme(axis.title.y = element_text(size = 12),
        axis.title.x = element_text(size = 12),
        axis.text.x = element_text(size = 7)) +
  scale_x_date(breaks = "3 months", date_labels = "%b %d")

#Tornar gráfico interativo
ggplotly(internados_confirmados_grafico, tooltip = "text") %>% 
  layout(yaxis = list(title = paste0(c(rep("&nbsp;", 20),
                                       "Taxa de Internamento (%)",
                                       rep("&nbsp;", 20),
                                       rep("\n&nbsp;", 2)),
                                     collapse = "")),
         legend = list(x = 1, y = 0))

Rácio entre Internados UCI e Internados


Neste gráfico podemos ver que no início da pandemia, uma vez que apenas os casos mais graves eram diagnosticados, cerca de 30% dos internados encontravam-se na unidade de cuidados intensivos. Desde o início de abril este rácio tem vindo a diminuir. Teve um aumento ligeiro no dia 16 de maio, provavelmente resultante dos 52 surtos ativos em lares de idosos existentes de 1 a 7 de maio. No início do verão houve um novo aumento provavelmente também resultante dos surtos ativos em estruturas residenciais para idosos.

Posteriormente o rácio foi diminuindo de forma considerável até dia 10 de agosto, onde atingiu o seu mínimo com cerca de 7%. De seguida, o rácio tem vindo novamente a aumentar devido a um aumento da incidência na população mais velha (gráfico Evolução da Incidência por Faixa Etária).

#Fazer o rácio
racio_internados <- cbind(covid19pt$data, as.data.frame((covid19pt$internados_uci/covid19pt$internados)*100))
names(racio_internados) = c("Data", "Racio")

#Fazer o gráfico
racio_internados_grafico <- ggplot(racio_internados, aes(x = Data, y = Racio)) + 
  geom_line(color = "tomato4", size=0.5) +
  geom_point(color = "tomato4", size=0.1, aes(text = paste( 'Data: ', Data,
                                         '<br>Rácio (%) :', Racio))) +
  labs(x = "",
       y = "Rácio (%)") +
  scale_x_date(breaks = "3 months", date_labels = "%b %d")


#Tornar interativo
ggplotly(racio_internados_grafico, tooltip = "text")


Recuperados


É importante analisar-se o número de recuperados para se poder avaliar de que forma o tipo de tratamento e/ou cuidados aplicados estão a ser eficazes.


Evolução da Taxa de Recuperados


Nos meses de março e abril a taxa de recuperados era bastante baixa. Isto pode ser justificado pelo facto de apenas os casos graves terem sido diagnosticados nesta fase. A partir de abril, a taxa de recuperados sofreu um crescimento devido ao aumento do número de diagnósticos de casos menos graves. No dia 24/05/2020, a taxa de recuperados teve uma subida abrupta, que pode dever-se a um lapso no registo dos recuperados. No dia 25/08/2020 ocorreu o pico. Desde então, a taxa tem vindo a diminuir de forma gradual, o que pode ser devido ao grande aumento do número de casos verificados em setembro, os quais ainda não tiveram tempo para recuperar.

#Criar tabela com coluna para data e outra coluna para a percentagem de recuperados em cada dia e dar nomes às colunas
recuperados <- cbind(covid19pt$data, as.data.frame((covid19pt$recuperados / covid19pt$confirmados)*100))
names(recuperados) <- c("Data", "Recuperados")

#Fazer gráfico de linhas com data no eixo do x e percentagem recuperados no eixo y
recuperados_grafico <- ggplot(recuperados, aes(x = Data, y = Recuperados)) +
  geom_line(color = "salmon1", size = 0.5) +
  geom_point(color = "salmon1", size=0.1, aes(text = paste( 'Data: ', Data,
                                         '<br>Taxa de Recuperados (%) :', Recuperados))) +
  labs(x = "",
       y = "Taxa de Recuperados (%)") +
  theme(axis.title.y = element_text(size = 12),
        axis.title.x = element_text(size = 12)) +
  scale_x_date(breaks = "3 months", date_labels = "%b %d")

#Tornar gráfico interativo
ggplotly(recuperados_grafico, tooltip = "text") %>% 
  layout(yaxis = list(title = paste0(c(rep("&nbsp;", 20),
                                       "Taxa de Recuperados (%)",
                                       rep("&nbsp;", 20),
                                       rep("\n&nbsp;", 2)),
                                     collapse = "")))
LS0tCnRpdGxlOiAiQW7DoWxpc2UgQ09WSUQtMTkiCmF1dGhvcjogIkVzdGFnacOhcmlhcyIKZGF0ZTogIjMwLzA5LzIwMjAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICBkZl9wcmludDogcGFnZWQKICAgIHRoZW1lOiBsdW1lbgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogMwogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6ICczJwogIGh0bWxfbm90ZWJvb2s6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIHRoZW1lOiBsdW1lbgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogMwogICAgdG9jX2Zsb2F0OiB5ZXMKZWRpdG9yX29wdGlvbnM6IAogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUKLS0tCgoKPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KLm1haW4tY29udGFpbmVyIHsKICBtYXgtd2lkdGg6IDEwMDBweDsKICBtYXJnaW4tbGVmdDogYXV0bzsKICBtYXJnaW4tcmlnaHQ6IGF1dG87Cn0KPC9zdHlsZT4KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmBgYAoKYGBge2NzcywgZWNobz1GQUxTRX0KLyogV2hvbGUgZG9jdW1lbnQ6ICovCmJvZHl7CiAgZm9udC1zaXplOiAxMnB0Owp9CmBgYAoKCjxicj4KCiMjICoqSW50cm9kdcOnw6NvKioKKioqCgpDb20gZXN0ZSByZWxhdMOzcmlvIHByZXRlbmRlbW9zIGZhemVyIHVtYSBhbsOhbGlzZSBzb2JyZSBhIENPVklELTE5IGVtIFBvcnR1Z2FsLCBjb20gYmFzZSBub3MgZGFkb3MgZGEgREdTIGRpc3BvbsOtdmVpcyBlbTogPGh0dHBzOi8vZ2l0aHViLmNvbS9kc3NnLXB0L2NvdmlkMTlwdC1kYXRhPi4KCkVzdGUgcmVsYXTDs3JpbyB0ZW0gY29tbyBvYmpldGl2byByZWFsaXphciB1bWEgYW7DoWxpc2UgZGV0YWxoYWRhIGRvcyBzZWd1aW50ZXMgdMOzcGljb3M6Cjx1bD4KICA8bGk+U2ludG9tYXM8L2xpPgogIDxsaT5UZXN0YWdlbTwvbGk+CiAgPGxpPkNhc29zPC9saT4KICA8bGk+TW9ydGVzPC9saT4KICA8bGk+SW50ZXJuYW1lbnRvczwvbGk+CiAgPGxpPlJlY3VwZXJhw6fDo288L2xpPgo8L3VsPgoKTm90YTogSG91dmUgdW0gbGFwc28gbmEgYmFzZSBkZSBkYWRvcyBlIG9zIMOzYml0b3MgY3VtdWxhdGl2b3MgcG9yIGlkYWRlIGUgcG9yIHNleG8gcGFyYSBkaWEgNS8xMCBlc3TDo28gdG9kb3MgYSAwLiBTdWJpdHVpbW9zIGVzc2VzIDAncyBwZWxvcyB2YWxvcmVzIGRvIGRpYSBhbnRlcmlvci4KCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiNMaWJyYXJpZXMKbGlicmFyeShkYXRhLnRhYmxlKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkobHVicmlkYXRlKQpsaWJyYXJ5KHNjYWxlcykKbGlicmFyeShncmlkKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpYmJsZSkKbGlicmFyeShyZXNoYXBlMikKbGlicmFyeShnZ3B1YnIpCmxpYnJhcnkobWFwcykKbGlicmFyeShnZ2lyYXBoKQpsaWJyYXJ5KGxlYWZsZXQpCmxpYnJhcnkoZ2VvanNvbmlvKQpsaWJyYXJ5KGdnYW5pbWF0ZSkKbGlicmFyeShwbG90bHkpCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpsaWJyYXJ5KHNmKQpsaWJyYXJ5KGdyaWQpCmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KGh0bWx0b29scykKbGlicmFyeSh6b28pCgojSW1wb3J0YXIgZGFkb3MKY292aWQxOXB0IDwtIGZyZWFkKCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vZHNzZy1wdC9jb3ZpZDE5cHQtZGF0YS9tYXN0ZXIvZGF0YS5jc3YiKQpjb3ZpZDE5cHRfdGVzdGVzIDwtIGZyZWFkKCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vZHNzZy1wdC9jb3ZpZDE5cHQtZGF0YS9tYXN0ZXIvYW1vc3RyYXMuY3N2IikKCiMgVHJhdGFyIGJhc2UgZGUgZGFkb3MgZG8gY292aWQKCiMjIEhvdXZlIHVtIGxhcHNvIG5hIGJhc2UgZGUgZGFkb3MgZSBvcyBvYml0b3MgY3VtdWxhdGl2b3MgcG9yIGlkYWRlIGUgcG9yIHNleG8gcGFyYSBkaWEgNS8xMCAobGluaGEgMjIzKSBlc3RhbyBhIDAncy4gU3ViaXR1aW1vcyBlc3NlcyAwJ3MgcGVsb3MgbWVzbW9zIHZhbG9yZXMgZG8gZGlhIGFudGVyaW9yCgpjb3ZpZDE5cHRbMjIzLCA2NTo4NF0gPSBjb3ZpZDE5cHRbMjIyLCA2NTo4NF0KCiNEYXRhIGRlIGNociBwYXJhIERhdGUKY292aWQxOXB0JGRhdGEgPC0gYXMuRGF0ZShjb3ZpZDE5cHQkZGF0YSwiJWQtJW0tJVkiKQpjb3ZpZDE5cHRfdGVzdGVzJGRhdGEgPC0gYXMuRGF0ZShjb3ZpZDE5cHRfdGVzdGVzJGRhdGEsIiVkLSVtLSVZIikKCiNNYXBhIGRlIFBvcnR1Z2FsCm1hcGFfcHQgPC0gZ2VvanNvbl9yZWFkKCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vZHNzZy1wdC9jb3ZpZDE5cHQtZGF0YS9tYXN0ZXIvZXh0cmEvbWFwYXMvcG9ydHVnYWwuZ2VvanNvbiIsd2hhdCA9ICJzcCIpCmBgYAoKCiMjICoqU2ludG9tYXMqKiB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30KKioqCgpOYSBiYXNlIGRlIGRhZG9zIHV0aWxpemFkYSwgYXMgY29sdW5hcyA0MSDDoCA0NiBhcHJlc2VudGFtIGEgcGVyY2VudGFnZW0gZGUgY2Fzb3MgaW5mZXRhZG9zIHF1ZSByZXBvcnRhcmFtIG8gc2ludG9tYSByZXNwZXRpdm8uIE8gY29tcG9ydGFtZW50byBkb3MgZGFkb3MgbGV2YS1ub3MgYSBjcmVyIHF1ZSBlc3RlcyB2YWxvcmVzIHNlamFtIGN1bXVsYXRpdm9zLgoKRXN0ZXMgZGFkb3Mgc8OzIGZvcmFtIHJlZ2lzdGFkb3MgZGUgZGlhIDAzLzAzLzIwMjAgYXTDqSBkaWEgMTYvMDgvMjAyMCBlLCBwYXJhIGFsw6ltIGRpc3NvLCB0YWwgY29tbyDDqSByZWZlcmlkbyBuYSBiYXNlIGRlIGRhZG9zIG9ubGluZSwgZXN0ZXMgZGFkb3Mgc8OjbyByZWxhdGl2b3MgYXBlbmFzIGEgdW1hIHBlcmNlbnRhZ2VtLCBuw6NvLWVzcGVjaWZpY2FkYSBlIHZhcmnDoXZlbCwgZG9zIGNhc29zIGluZmV0YWRvcy4gUG9yIGVzdGUgbW90aXZvLCBhcGVzYXIgZGUgdGVybW9zIHJlYWxpemFkbyBkdWFzIGFuw6FsaXNlcywgZXN0ZXMgcmVzdWx0YWRvcyBwb2RlbSBuw6NvIHNlciBmacOhdmVpcyBuZW0gcmVwcmVzZW50YXRpdm9zIGRhIHJlYWxpZGFkZS4KCjxicj48YnI+CgojIyMgRnJlcXXDqm5jaWEgUmVsYXRpdmEKPGJyPgoKT3MgdmFsb3JlcyBhcHJlc2VudGFkYXMgbmVzdGUgZ3LDoWZpY28gZGUgYmFycmFzIHJlZmVyZW0tc2Ugw6AgcGVyY2VudGFnZW0gZGUgY2Fzb3MgaW5mZXRhZG9zIHF1ZSByZXBvcnRhcmFtIGNhZGEgdW0gZG9zIHNpbnRvbWFzLiBPIHNpbnRvbWEgbWFpcyBmcmVxdWVudGUgZm9pIGEgdG9zc2UgY29tIDM0JSBkb3MgaW5mZXRhZG9zIGEgYXByZXNlbnRhcmVtIGVzc2Ugc2ludG9tYSwgc2VndWluZG8tc2UgYSBmZWJyZSBjb20gMjclIGUgYSBjZWZhbGVpYSBlIGRvcmVzIG11c2N1bGFyZXMgYW1ib3MgY29tIDIwJS4KCmBgYHtyIHByZXNzdXJlLCBmaWcuYWxpZ249J2NlbnRlcicsIHdhcm5pbmc9RkFMU0V9CiNDcmlhciB1bWEgdGFiZWxhIGNvbSB1bWEgY29sdW5hIHBhcmEgb3Mgc2ludG9tYXMsIGRhci1saGUgbyBub21lICJzaW50b21hIiwgbXVkYXIgbyBub21lIGRlIGNhZGEgc2ludG9tYSBuYSB0YWJlbGEgZSBjcmlhciBvdXRyYSBjb2x1bmEgcGFyYSBvcyDDumx0aW1vcyB2YWxvcmVzIHJlZ2lzdGFkb3MgZGUgY2FkYSBzaW50b21hIGUgZGFyLWxoZSBvIG5vbWUgImZyZXF1ZW5jaWEiCnNpbnRvbWFzIDwtIGFzLmRhdGEuZnJhbWUodChjb3ZpZDE5cHRbMTczLDQxOjQ2XSkpICU+JSAKICByb3duYW1lc190b19jb2x1bW4odmFyID0gInNpbnRvbWEiKQpuYW1lcyhzaW50b21hcylbMl0gPSAiZnJlcXVlbmNpYSIKc2ludG9tYXNbLCAxXSA9IGMoIlRvc3NlIiwgIkZlYnJlIiwgIkRpZmljdWxkYWRlIFJlc3BpcmF0w7NyaWEiLCAiQ2VmYWxlaWEiLCAiRG9yZXMgTXVzY3VsYXJlcyIsICJGcmFxdWV6YSBHZW5lcmFsaXphZGEiKQoKI0ZhemVyIHVtIGdyw6FmaWNvIGRlIGJhcnJhcyBjb20gb3Mgc2ludG9tYXMgbm8gZWl4byBkbyB4IGUgYSBwZXJjZW50YWdlbSBubyBlaXhvIGRvcyB5CmdncGxvdChzaW50b21hcywgYWVzKHggPSBzaW50b21hLCB5ID0gZnJlcXVlbmNpYSoxMDApKSArCiAgZ2VvbV9jb2woZmlsbCA9ICJzbGF0ZWdyYXkzIiwgIHdpZHRoID0gMC43KSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsKICBjb29yZF9jYXJ0ZXNpYW4oIHlsaW0gPSBjKDAsIG1heChzaW50b21hcyRmcmVxdWVuY2lhKjEwMCArIDEwKSkpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIGxhYnMoeCA9ICIiLAogICAgICAgeSA9ICJGcmVxdcOqbmNpYSAoJSkiKSArCiAgdGhlbWUoYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbihyID0gMTUsIGwgPSAxMCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMTIpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siKSkgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBzY2FsZXM6OnBlcmNlbnQoZnJlcXVlbmNpYSwgZGlnaXRzID0gMikpLCAKICAgICAgICAgICAgdmp1c3QgPSAtMC41LCAKICAgICAgICAgICAgc2l6ZSA9IDQpICsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGMoIkNlZmFsZWlhIiwgIkRpZmljdWxkYWRlXG5SZXNwaXJhdMOzcmlhIiwgIkRvcmVzXG5NdXNjdWxhcmVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkZlYnJlIiwgIkZyYXF1ZXphXG5HZW5lcmFsaXphZGEiLCAiVG9zc2UiKSkKYGBgCgoKCiMjIyBFdm9sdcOnw6NvIGRhIEZyZXF1w6puY2lhIFJlbGF0aXZhCjxicj4KUGFyYSBlbnRlbmRlciBtZWxob3IgZXN0ZSBncsOhZmljbyDDqSBuZWNlc3PDoXJpbyBwZXJjZWJlciBxdWUgb3MgdmFsb3JlcyBuZWdhdGl2b3MgaW5kaWNhbSBxdWUgaG91dmUgdW1hIGRpbWludWnDp8OjbyBuYSBwZXJjZW50YWdlbSBkZSBwZXNzb2FzIGNvbSBkZXRlcm1pbmFkbyBzaW50b21hIGNsw61uaWNvLiBPcyB2YWxvcmVzIHBvc2l0aXZvcyBpbmRpY2FtIHF1ZSBob3V2ZSB1bSBhdW1lbnRvIGRlc3NhIHBlcmNlbnRhZ2VtIHNlbmRvIHF1ZSBvcyB2YWxvcmVzIHBvc2l0aXZvcyBtZW5vcmVzIGRvIHF1ZSBvIGRvIGRpYSBhbnRlcmlvciwgc2lnbmlmaWNhbSBxdWUgaG91dmUgY3Jlc2NpbWVudG8sIG1hcyBtZW5vci4KCkFzc2ltLCDDqSBwb3Nzw612ZWwgdmVyaWZpY2FyIHF1ZSBpbmljaWFsbWVudGUgZXhpc3RpdSB1bWEgZ3JhbmRlIHZhcmlhw6fDo28gbmEgZnJlcXXDqm5jaWEgZGUgY2Fzb3MgY29uZmlybWFkb3MgcXVlIHJlcG9ydGFyYW0gY2FkYSB1bSBkb3Mgc2ludG9tYXMuIMOJIGRlIG5vdGFyIHF1ZSBhIHBhcnRpciBkZSBqdW5obyBlc3RhIHZhcmlhw6fDo28gZm9pIHNlbmRvIGNhZGEgdmV6IG1lbm9yIHRvcm5hbmRvIG9zIHZhbG9yZXMgbWFpcyBjb25zdGFudGVzLCDDoCBleGNlw6fDo28gZGEgdG9zc2UuIAoKYGBge3IsIGZpZy5hbGlnbj0nY2VudGVyJywgd2FybmluZz1GQUxTRX0KI0NyaWFyIHVtYSB0YWJlbGEgY29tIGNvbHVuYXMsIHVtYSBwYXJhIGNhZGEgc2ludG9tYSwgc2VuZG8gbyB2YWxvciBwYXJhIGNhZGEgZGlhIGEgZnJlcXXDqm5jaWEgZGVzc2Ugc2ludG9tYSBuZXNzZSBkaWEgdmV6ZXMgbyBuw7ptZXJvIGRlIGNvbmZpcm1hZG9zIGF0w6kgZXNzZSBkaWEgbWVub3MgYSBmcmVxdcOqbmNpYSBkZXNzZSBzaW50b21hIG5vIGRpYSBhbnRlcmlvciB2ZXplcyBvIG7Dum1lcm8gZGUgY29uZmlybWFkb3MgYXTDqSBhbyBkaWEgYW50ZXJpb3IsIGlzdG8gcGFyYSBub3MgZGFyIG8gbsO6bWVybyBkZSBwZXNzb2FzIGNvbSBlc3NlIHNpbnRvbWEgbmVzc2UgZGlhIGFwZW5hcywgZSBkZXBvaXMgdHVkbyBhIGRpdmlkaXIgcGVsbyBuw7ptZXJvIGRlIG5vdm9zIGNvbmZpcm1hZG9zIG5lc3NlIGRpYSBwYXJhIHRlcm1vcyBvIHJlc3VsdGFkbyBlbSBwZXJjZW50YWdlbS4gCnNpbnRvbWFzX3RlbXBvIDwtIGFzLmRhdGEuZnJhbWUoKGNvdmlkMTlwdFs4OjE3Myw0MTo0Nl0qY292aWQxOXB0JGNvbmZpcm1hZG9zWzg6MTczXSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAtKGNvdmlkMTlwdFs3OjE3MiwgNDE6NDZdKmNvdmlkMTlwdCRjb25maXJtYWRvc1s3OjE3Ml0pKS9jb3ZpZDE5cHQkY29uZmlybWFkb3Nfbm92b3NbODoxNzNdIAoKI8OJIGFpbmRhIG5lY2Vzc8OhcmlvIGFjcmVzY2VudGFyIGEgbGluaGEgNyBwb2lzIGNvbW8gc8OjbyBhcyBwcmltZXJpYXMgZnJlcXXDqm5jaWFzIGEgYXBhcmVjZXIgasOhIGluZGljYW0gYSBmcmVxdcOqbmNpYSBlc3BlY8OtZmljYSBwYXJhIGVzc2UgZGlhCnNpbnRvbWFzX3RlbXBvIDwtIHJiaW5kKGNvdmlkMTlwdFs3LCA0MTo0Nl0sIHNpbnRvbWFzX3RlbXBvKQoKI0FjcmVzY2VudGFyIMOgIHRhYmVsYSBxdWUgY3Jpw6Ftb3MsIHVtYSBjb2x1bmEgY29tIGFzIGRhdGFzCnNpbnRvbWFzX3RlbXBvIDwtIGNiaW5kKGNvdmlkMTlwdCRkYXRhWzc6MTczXSwgc2ludG9tYXNfdGVtcG8pCgojTm8gY2Fzb3MgZG8gc2ludG9tYSBEaWZpY3VsZGFkZSBSZXNwaXJhdMOzcmlhLCBlc3RlIHPDsyBjb21lw6dvdSBhIHNlciByZWdpc3RhZG8gbWFpcyB0YXJkZSBwZWxvIHF1ZSBvIHByaW1lcmlvIHZhbG9yIHF1ZSBqw6EgcmVwcmVzZW50YSBhIGZyZXF1w6puY2lhIGVzcGVjw61maWNhIHBhcmEgZXNzZSBkaWEgw6kgbyBkYSBsaW5oYSAzLCBjb2x1bmEgNApzaW50b21hc190ZW1wb1szLCA0XSA8LSAwLjExCgojTXVkYXIgb3Mgbm9tZXMgZGFzIGNvbHVuYXMKbmFtZXMoc2ludG9tYXNfdGVtcG8pIDwtIGMoIkRhdGEiLCAiVG9zc2UiLCAiRmVicmUiLCAiRGlmaWN1bGRhZGUgXG5yZXNwaXJhdMOzcmlhIiwgIkNlZmFsZWlhIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJEb3JlcyBcbk11c2N1bGFyZXMiLCAgIkZyYXF1ZXphIFxuR2VuZXJhbGl6YWRhIikKCiNGYXplciBvIG1lbHQgZGEgdGFibGVhIHBhcmEgcG9kZXIgcmVwcmVzZW50YXIgYSBlY29sdcOnw6NvIHRlbXBvcmFsIG51bSBncsOhZmljbyBlIG11ZGFyIG8gbm9tZSBkYSBjb2x1bmEgMiBwYXJhIFNpbnRvbWFzCnNpbnRvbWFzX3RlbXBvX21lbHQgPC0gIG1lbHQoc2ludG9tYXNfdGVtcG8sIGlkLnZhcnM9IkRhdGEiKQpuYW1lcyhzaW50b21hc190ZW1wb19tZWx0KVsyXSA8LSAic2ludG9tYSIKI0ZhemVyIHVtIGdyw6FmaWNvIGRlIGxpbmhhcyBjb20gYSBkYXRhIG5vIGVpeG8gZG8geCwgYSBmcmVxdcOqbmNpYSBkacOhcmlhIGRvcyBzaW50b21hcyBubyBlaXhvIGRvcyB5IGUgY2FkYSBzaW50b21hIG51bWEgbGluaGEKZ2dwbG90KHNpbnRvbWFzX3RlbXBvX21lbHQsIGFlcyh4ID0gRGF0YSwgeSA9IHZhbHVlKjEwMCwgY29sb3IgPSBzaW50b21hKSkgKwogIGdlb21fbGluZSgpICsKICBmYWNldF9ncmlkKHNpbnRvbWFzX3RlbXBvX21lbHQkc2ludG9tYSkgKwogIGd1aWRlcyhjb2xvciA9IEZBTFNFKSArCiAgbGFicyh4ID0gIiIsCiAgICAgICB5ID0gIkZyZXF1w6puY2lhICglKSIpICsKICB0aGVtZShheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKHIgPSAxNSwgbCA9IDEwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEyKSwKICAgICAgICBzdHJpcC50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbmdsZSA9IDApKQpgYGAKCgo8YnI+CgojIyAqKlRlc3RhZ2VtKiogey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9CioqKgoKVW0gZG9zIGZhdG9yZXMgaW1wb3J0YW50ZXMgYSB0ZXIgZW0gY29udGEgw6kgbyBuw7ptZXJvIGRlIHBlc3NvYXMgdGVzdGFkYXMgcGFyYSBhIENPVklELTE5LiBBc3NpbSBzZW5kbywgdXRpbGl6w6Ftb3Mgb3V0cmEgYmFzZSBkZSBkYWRvcyBkYSBtZXNtYSBmb250ZSBwYXJhIG9idGVyIGluZm9ybWHDp8O1ZXMgcmVsYXRpdmFzIMOgIHRlc3RhZ2VtLgoKw4kgaW1wb3J0YW50ZSBub3RhciBxdWUgb3MgdmFsb3JlcyBkYSBiYXNlIGRlIGRhZG9zICoiY29ycmVzcG9uZGVtIGFvIG7Dum1lcm8gZGUgYW1vc3RyYXMgcHJvY2Vzc2FkYXMgcGFyYSBkaWFnbsOzc3RpY28gZGUgU0FSUy1Db1YtMiBlbSBsYWJvcmF0w7NyaW9zIHDDumJsaWNvcyBlIHByaXZhZG9zIGRlc2RlIG8gZGlhIDEgZGUgbWFyw6dvLiIqIFBhcmEgYWzDqW0gZGlzc28sIG5vIGRhc2hib2FyZCBkYSBER1MgZGl6ZW0gYWluZGEgcXVlICoiT3MgZGFkb3MgZGnDoXJpb3MgYXDDs3MgMiBkZSBhYnJpbCBkZSAyMDIwIGFpbmRhIGVzdMOjbyBhIHNlciByZWNvbGhpZG9zLCBwZWxvIHF1ZSBvcyB2YWxvcmVzIG5vIGdyw6FmaWNvIHBvZGVyw6NvIHNvZnJlciBhbHRlcmHDp8O1ZXMuIiogRXhpc3RlIGEgcG9zc2liaWxpZGFkZSBkZSwgYSBjYWRhIGRpYSwgZGFkb3MgcmVmZXJlbnRlcyBhIGRpYXMgYW50ZXJpb3JlcyBzZXJlbSBhbHRlcmFkb3MsIHByb3ZhdmVsbWVudGUgcGVsbyBmYWN0byBkYSBpbmZvcm1hw6fDo28gcmVsYXRpdmEgYW8gcHJvY2Vzc2FtZW50byBkZSBhbW9zdHJhcyBzZXIgcmVjZWJpZGEgcGVsYSBER1MgY29tIGFsZ3VucyBkaWFzIGRlIGRlc2Zhc2FtZW50by4KCjxicj4KCiMjIyBFdm9sdcOnw6NvIGRvIE7Dum1lcm8gZGUgVGVzdGVzIFJlYWxpemFkb3MKPGJyPgpDb20gYSBhbsOhbGlzZSBkZXN0ZSBncsOhZmljbyDDqSBwb3Nzw612ZWwgdmVyaWZpY2FyIHF1ZSBvIG7Dum1lcm8gZGUgdGVzdGVzIGRpw6FyaW9zIHJlYWxpemFkb3MgdGVtIHZpbmRvIGEgZGVtb25zdHJhciB1bWEgdGVuZMOqbmNpYSBjcmVzY2VudGUuIAoKw4kgYWluZGEgcG9zc8OtdmVsIHRpcmFyIG91dHJhcyBjb25jbHVzw7Vlcywgbm9tZWFkYW1lbnRlIHF1ZSBvcyBkaWFzIGNvbSBtZW5vciB0ZXN0YWdlbSBzw6NvICBtYWlvcml0YXJpYW1lbnRlIG8gZG9taW5nbywgbWFzIHRhbWLDqW0gbyBzw6FiYWRvLCBlIHF1ZSBvcyBkaWFzIGNvbSBtYWlvciB0ZXN0YWdlbSBzw6NvIHByaW5jaXBhbG1lbnRlIGFzIHRlcsOnYXMgZSBxdWFydGFzLgoKYGBge3IsZmlnLmFsaWduPSdjZW50ZXInLCB3YXJuaW5nPUZBTFNFfQojVGFiZWxhIGNvbSBjb2x1bmEgcGFyYSBkYXRhIGUgb3V0cmEgcGFyYSBuw7ptZXJvIGRlIHRlc3RlcyBmZWl0b3MgbmVzc2UgZGlhCnRlc3Rlc19kaWFyaW9zIDwtIGNvdmlkMTlwdF90ZXN0ZXNbLGMoMSwgMyldCm5hbWVzKHRlc3Rlc19kaWFyaW9zKSA9IGMoIkRhdGEiLCAiVGVzdGVzIikKCiNHcsOhZmljbyBkZSBwb250b3MgZSBsaW5oYXMgY29tIGRhdGEgbm8gZWl4byBkbyB4IGUgbsO6bWVybyBkZSB0ZXN0ZXMgbm8gZWl4byBkbyB5CnRlc3Rlc19kaWFyaW9zX2dyYWZpY28gPC0gZ2dwbG90KHRlc3Rlc19kaWFyaW9zLCBhZXMoeCA9IERhdGEsIHkgPSBUZXN0ZXMpKSArIAogIGdlb21fcG9pbnQoY29sb3IgPSAiY2FkZXRibHVlIiwgYWVzKHRleHQgPSBwYXN0ZSgnRGF0YTogJywgRGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJzxicj5Ow7ptZXJvIGRlIHRlc3RlczogJywgVGVzdGVzKSkpICsKICBnZW9tX2xpbmUoc2l6ZSA9IDAuNCwgY29sb3IgPSAiY2FkZXRibHVlIikgKwogIGxhYnMoeCA9ICIiKSArCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMikpICsKICBzY2FsZV94X2RhdGUoYnJlYWtzID0gIjMgbW9udGhzIiwgZGF0ZV9sYWJlbHMgPSAiJWIgJWQiKQoKI0ZhemVyIGNvbSBxdWUgZ3LDoWZpY28gc2VqYSBpbnRlcmF0aXZvCnRlc3Rlc19kaWFyaW9zX2dyYWZpY29faW50ZXJhdGl2byA8LSBnZ3Bsb3RseSh0ZXN0ZXNfZGlhcmlvc19ncmFmaWNvLCAgdG9vbHRpcCA9ICJ0ZXh0IikgJT4lIAogIGxheW91dCh5YXhpcyA9IGxpc3QodGl0bGUgPSBwYXN0ZTAoYyhyZXAoIiZuYnNwOyIsIDIwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk7Dum1lcm8gZGUgVGVzdGVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCImbmJzcDsiLCAyMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcCgiXG4mbmJzcDsiLCAyKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xsYXBzZSA9ICIiKSkpCgojVGVzdGFnZW0gY29tIG3DqWRpYSByb2xhbnRlIDcgZGlhcwojI0ZhemVyIGEgbcOpZGlhIHJvbGFudGUKdGVzdGVzX21lZGlhX3JvbGFudGUgPC0gY2JpbmQoY292aWQxOXB0X3Rlc3Rlc1s3Om5yb3coY292aWQxOXB0X3Rlc3RlcyksMV0sIHJvbGxtZWFuKGNvdmlkMTlwdF90ZXN0ZXNbLDNdLCBrID0gNykpCm5hbWVzKHRlc3Rlc19tZWRpYV9yb2xhbnRlKSA9IGMoIkRhdGEiLCAiVGVzdGVzIikKCiMjRmF6ZXIgbyBncsOhZmljbwp0ZXN0ZXNfbWVkaWFfcm9sYW50ZV9ncmFmaWNvIDwtIGdncGxvdCh0ZXN0ZXNfbWVkaWFfcm9sYW50ZSwgYWVzKHggPSBEYXRhLCB5ID0gVGVzdGVzKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDAuMSwgY29sb3IgPSAiY2FkZXRibHVlIiwgYWVzKHRleHQgPSBwYXN0ZSgnRGF0YTogJywgRGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJzxicj5Ow7ptZXJvIGRlIHRlc3RlczogJywgVGVzdGVzKSkpICsKICBnZW9tX2xpbmUoc2l6ZSA9IDAuNSwgY29sb3IgPSAiY2FkZXRibHVlIikgKwogIGxhYnModGl0bGUgPSAiTcOpZGlhIFJvbGFudGUgKDcgZGlhcykiLAogICAgICAgeCA9ICIiLAogICAgICAgeSA9ICJOw7ptZXJvIGRlIFRlc3RlcyIpICsKICBzY2FsZV94X2RhdGUoYnJlYWtzID0gIjMgbW9udGhzIiwgZGF0ZV9sYWJlbHMgPSAiJWIgJWQiKQoKIyNGYXplciBjb20gcXVlIGdyw6FmaWNvIHNlamEgaW50ZXJhdGl2bwp0ZXN0ZXNfbWVkaWFfcm9sYW50ZV9ncmFmaWNvX2ludGVyYXRpdm8gPC0gZ2dwbG90bHkodGVzdGVzX21lZGlhX3JvbGFudGVfZ3JhZmljbywgIHRvb2x0aXAgPSAidGV4dCIpCgpicm93c2FibGUoCiAgdGFnTGlzdChsaXN0KAogICAgdGFncyRkaXYoCiAgICAgIHN0eWxlID0gJ3dpZHRoOjUwJTtkaXNwbGF5OmJsb2NrO2Zsb2F0OmxlZnQ7JywKICAgICAgdGVzdGVzX2RpYXJpb3NfZ3JhZmljb19pbnRlcmF0aXZvCiAgICApLAogICAgdGFncyRkaXYoCiAgICAgIHN0eWxlID0gJ3dpZHRoOjUwJTtkaXNwbGF5OmJsb2NrO2Zsb2F0OmxlZnQ7JywKICAgICAgdGVzdGVzX21lZGlhX3JvbGFudGVfZ3JhZmljb19pbnRlcmF0aXZvCiAgICApCiAgKSkKKQoKYGBgCgoKCiMjIyBFdm9sdcOnw6NvIGRhIFRheGEgZGUgVGVzdGVzIFBvc2l0aXZvcwo8YnI+ClNlZ3VuZG8gbyBncsOhZmljbyBkZSBsaW5oYXMsIGVtIGFicmlsIHZlcmlmaWNvdS1zZSBhIG1haW9yIHBlcmNlbnRhZ2VtIGRlIHRlc3RlcyBwb3NpdGl2b3MgZmFjZSBhbyBuw7ptZXJvIGRlIHRlc3RlcyB0b3RhaXMsIGNvbSB2YWxvcmVzIHBlcnRvIGRvcyAxNSUuIEEgcGFydGlyIGRhw60gZXN0YSBwZXJjZW50YWdlbSB0ZW0gdmluZG8gYSBkaW1pbnVpciBvIHF1ZSBtb3N0cmEgcXVlOiBow6EgbWVub3MgY2Fzb3MgcG9zaXRpdm9zIGUvb3UgaMOhIG1haXMgdGVzdGVzIGEgc2VyZW0gcmVhbGl6YWRvcyBwb3IgZGlhLiBOb3Mgw7psdGltb3MgbWVzZXMgYSBwZXJjZW50YWdlbSBmb2kgcXVhc2Ugc2VtcHJlIG1lbm9yIGRvIHF1ZSA1JSBvIHF1ZSwgZmFjZSBhb3MgbWVzZXMgYW50ZXJpb3JlcywgcG9kZSBkZW1vbnN0cmFyIHF1ZSBhIHRlc3RhZ2VtIHRlbSBzaWRvIG1haXMgYWJyYW5nZW50ZSwgc2VuZG8gcHJvdsOhdmVsIHF1ZSBzZSBlc3RlamEgYSB0ZXN0YXIgZ3JhbmRlIHBhcnRlIGRvcyBjYXNvcyBwb3NpdGl2b3MuCgpBbMOpbSBkaXNzbywgcG9kZW1vcyB2ZXIgcXVlLCBwcmluY2lwYWxtZW50ZSBhbyBkb21pbmdvLCBhIHBlcmNlbnRhZ2VtIGRlIHRlc3RlcyBwb3NpdGl2b3Mgw6kgY29uc3RhbnRlbWVudGUgbWFpb3IgZmFjZSBhb3Mgb3V0cm9zIGRpYXMgZGEgc2VtYW5hLiBFc3RhIGluZm9ybWHDp8OjbyDDqSBjb2VyZW50ZSBjb20gbyBncsOhZmljbyBhbnRlcmlvciwgdW1hIHZleiBxdWUgw6kgbmVzdGVzIGRpYXMgcXVlIHNlIHZlcmlmaWNhIHVtIG1lbm9yIG7Dum1lcm8gZGUgdGVzdGVzIGRpw6FyaW9zIGUgYXNzaW0sIHN1cG9tb3MgcXVlIGTDo28gcHJpbWF6aWEgYW9zIGNhc29zIG1haXMgdXJnZW50ZXMsIGF1bWVudGFuZG8gYXNzaW0gYSBwZXJjZW50YWdlbSBkZSB0ZXN0ZXMgcG9zaXRpdm9zIGFvIGRvbWluZ28uIE8gY29udHLDoXJpbyB2ZXJpZmljYS1zZSDDoCB0ZXLDp2EsIGRpYSBlbSBxdWUgc8OjbyB0ZXN0YWRhcyBtYWlzIHBlc3NvYXMsIGV4aXN0aW5kbyBub3JtYWxtZW50ZSB1bWEgbWVub3IgcGVyY2VudGFnZW0gZGUgdGVzdGVzIHBvc2l0aXZvcy4KCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQojVGFiZWxhIGNvbSBjb2x1bmEgcGFyYSBkYXRhIGUgY29sdW5hIHBhcmEgbsO6bWVybyBkZSBjYXNvcyBjb25maXJtYWRvcyBuZXNzZSBkaWEKY2Fzb3NfZGlhcmlvcyA8LSBjb3ZpZDE5cHRbLCBjKDEsIDEyKV0KbmFtZXMoY2Fzb3NfZGlhcmlvcykgPSBjKCJEYXRhIiwgIkNhc29zIikKCiMjI1RhYmVsYSBjb20gY29sdW5hIHBhcmEgZGF0YSBlIG91dHJhIHBhcmEgY2Fzb3MgZGVzc2UgZGlhIGEgZGl2aWRpciBwb3IgbsO6bWVybyBkZSB0ZXN0ZXMgZGVzc2UgZGlhCnRlc3Rlc19wb3NpdGl2b3MgPC0gY2JpbmQodGVzdGVzX2RpYXJpb3NbLDFdLCBhcy5kYXRhLmZyYW1lKChjYXNvc19kaWFyaW9zWzE6bnJvdyh0ZXN0ZXNfZGlhcmlvcyksMl0vdGVzdGVzX2RpYXJpb3NbLDJdKSoxMDApKQpuYW1lcyh0ZXN0ZXNfcG9zaXRpdm9zKSA9IGMoIkRhdGEiLCAiUGVyY2VudGFnZW1fUG9zaXRpdm9zIikKCiMjI0ZhemVyIGdyw6FmaWNvIGNvbSBkYXRhIG5vIGVpeG8gZG8geCBlIHByb3BvcsOnw6NvIGRlIHRlc3RlcyBwb3NpdGl2b3Mgbm8gZWl4byBkbyB5CnRlc3Rlc19wb3NpdGl2b3NfZ3JhZmljbyA8LSBnZ3Bsb3QodGVzdGVzX3Bvc2l0aXZvcywgYWVzKHggPSBEYXRhLCB5ID0gUGVyY2VudGFnZW1fUG9zaXRpdm9zKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJsaWdodHNlYWdyZWVuIikgKwogIGdlb21fcG9pbnQoY29sb3IgPSAibGlnaHRzZWFncmVlbiIsIGFlcyh0ZXh0ID0gcGFzdGUoJ0RhdGE6ICcsIERhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+VGF4YSBkZSBUZXN0ZXMgUG9zaXRpdm9zICglKTogJywgUGVyY2VudGFnZW1fUG9zaXRpdm9zKSkpICsKICBsYWJzKHggPSAiIiwKICAgICAgIHkgPSAiRnJlcXXDqm5jaWEgKCUpIikgKwogIHNjYWxlX3hfZGF0ZShicmVha3MgPSAiMyBtb250aHMiLCBkYXRlX2xhYmVscyA9ICIlYiAlZCIpCgojIyNGYXplciBjb20gcXVlIGdyw6FmaWNvIHNlamEgaW50ZXJhdGl2bwpnZ3Bsb3RseSh0ZXN0ZXNfcG9zaXRpdm9zX2dyYWZpY28sICB0b29sdGlwID0gInRleHQiKSAlPiUgCiAgbGF5b3V0KHlheGlzID0gbGlzdCh0aXRsZSA9IHBhc3RlMChjKHJlcCgiJm5ic3A7IiwgMjApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVGF4YSBkZSBUZXN0ZXMgUG9zaXRpdm9zICglKSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcCgiJm5ic3A7IiwgMjApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXAoIlxuJm5ic3A7IiwgMikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sbGFwc2UgPSAiIikpKQpgYGAKCjxicj4KCiMjICoqQ2Fzb3MqKiB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30KKioqCgpOZXN0ZSB0w7NwaWNvIHZhbW9zIGFib3JkYXIgYSBpbmNpZMOqbmNpYSAobsO6bWVybyBkZSBub3ZvcyBjYXNvcyBkacOhcmlvcyksIGEgdGF4YSBkZSBpbmNpZMOqbmNpYSAobsO6bWVybyBkZSBub3ZvcyBjYXNvcyBkacOhcmlvcy9wb3B1bGHDp8OjbyBlbSByaXNjbyksIG7Dum1lcm8gZGUgY2Fzb3MgY3VtdWxhdGl2b3MgZW0gdmFsb3IgYWJzb2x1dG8gZSBwcmV2YWzDqm5jaWEgKG7Dum1lcm8gdG90YWwgZGUgY2Fzb3MvcG9wdWxhw6fDo28pLgoKPGJyPgoKIyMjIEdlcmFsIHsudGFic2V0fQojIyMjIEV2b2x1w6fDo28gZGEgSW5jaWTDqm5jaWEKPGJyPgpOYSBsaW5oYSBkYSBpbmNpZMOqbmNpYSDDqSBwb3Nzw612ZWwgdmVyIHF1ZSBvIG7Dum1lcm8gZGUgY2Fzb3MgZGnDoXJpb3MgdGV2ZSB1bSBwaWNvIG5vIGRpYSAxMC8wNC8yMDIwLiBVbWEgdmV6IHF1ZSBvIG7Dum1lcm8gZGUgdGVzdGVzIG7Do28gYXVtZW50b3UgZGUgZm9ybWEgc2lnbmlmaWNhdGl2YSBub3MgZGlhcyBhbnRlcmlvcmVzLCB1bWEgZGFzIGp1c3RpZmljYcOnw7VlcyBwb3Nzw612ZWlzIMOpIHRlciBvY29ycmlkbyB1bSBsYXBzbyBuYSBub3RpZmljYcOnw6NvIGRvcyBjYXNvcyBuZXNzZSBkaWEuCgpQb2RlbW9zIGFpbmRhIGNvbnN0YXRhciB1bSBsaWdlaXJvIGF1bWVudG8gbm8gbsO6bWVybyBkZSBjYXNvcyBkdXJhbnRlIG9zIG1lc2VzIGRlIG1haW8gZSBqdW5oby4gRXN0ZSBhdW1lbnRvIHBvZGUgc2VyIGp1c3RpZmljYWRvIG5hIHNlcXXDqm5jaWEgZG8gcGVyw61vZG8gZGUgZsOpcmlhcywgcXVlIGFwZXNhciBkYXMgcmVzdHJpw6fDtWVzIGltcG9zdGFzLCBsZXZhIHNlbXByZSBhIHVtIGF1bWVudG8gZGFzIGRlc2xvY2HDp8O1ZXMgZSBhIHVtIG1haW9yIG7Dum1lcm8gZGUgY29udGFjdG9zIGVudHJlIHBlc3NvYXMuIEEgZGltaW51acOnw6NvIGRhIGluY2lkw6puY2lhIHZlcmlmaWNhZGEgZW50cmUganVsaG8gZSBhZ29zdG8gcG9kZSBzZXIganVzdGlmaWNhZGEgcGVsbyBmYWN0byBkb3MgcG9zc8OtdmVpcyBpbmZldGFkb3MgY29tIHNpbnRvbWFzIGxpZ2Vpcm9zIG7Do28gcmVjb3JyZXJlbSDDoCBsaW5oYSBkZSBzYcO6ZGUgMjQsIHBvciBuw6NvIHF1ZXJlcmVtIGZhemVyIHVtIGlzb2xhbWVudG8gcHJvZmlsw6F0aWNvIGR1cmFudGUgYXMgc3VhcyBmw6lyaWFzLgoKw4AgZGF0YSBkZXN0YSBhbsOhbGlzZSwgZGVzZGUgbyBpbsOtY2lvIGRlIHNldGVtYnJvLCBhIHN1YmlkYSBkbyBuw7ptZXJvIGRlIGNhc29zIHRlbSBzaWRvIGNyZXNjZW50ZSwgc2VuZG8gcG9zc8OtdmVpcyBqdXN0aWZpY2HDp8O1ZXM6Cjx1bD4KICA8bGk+UmVncmVzc28gZG9zIHRyYWJhbGhhZG9yZXMgYW8gZW1wcmVnbyBwcmVzZW5jaWFsPC9saT4KICA8bGk+UmVncmVzc28gZG9zIGpvdmVucyDDoHMgZXNjb2xhczwvbGk+CiAgPGxpPkF1bWVudG8gZGEgdGVzdGFnZW0gc29icmV0dWRvIGEgcGFydGlyIGRlIGRpYSAwOC8wOS8yMDIwPC9saT4KICA8bGk+UmVncmVzc28gYSB1bWEgdmlkYSBtYWlzIG5vcm1hbCBjb20gbWFpcyBjb250YWN0b3MgZW50cmUgcGVzc29hcyBlIG1lbm9zIGN1aWRhZG9zIGUgcHJlb2N1cGHDp8O1ZXMgZG8gcXVlIG5vIGluw61jaW8gZGEgcGFuZGVtaWE8L2xpPgo8L3VsPgoKTm8gZ3LDoWZpY28gZGEgRXZvbHXDp8OjbyBkYSBUYXhhIGRlIFRlc3RlcyBQb3NpdGl2b3MsIMOpIHBvc3PDrXZlbCB2ZXIgcXVlLCBkZXNkZSBvIGluw61jaW8gZGUgc2V0ZW1icm8sIHRlbSBoYXZpZG8gdW0gYXVtZW50byBuYSBwZXJjZW50YWdlbSBkZSBjYXNvcyBwb3NpdGl2b3MuIE5vIGVudGFudG8sIG7Do28gw6kgdW0gYXVtZW50byB0w6NvIGFjZW50dWFkbyBjb21vIGFxdWVsZSB2ZXJpZmljYWRvIG5lc3RlIGdyw6FmaWNvIGRhIEV2b2x1w6fDo28gZGEgSW5jaWTDqm5jaWEuIElzdG8gaW5kaWNhLW5vcyBxdWUgbyBhdW1lbnRvIGRvIG7Dum1lcm8gZGUgY2Fzb3MgbsOjbyDDqSB0b3RhbG1lbnRlIGV4cGxpY2FkbyBwZWxvIGF1bWVudG8gZG8gbsO6bWVybyBkZSB0ZXN0ZXMgcmVhbGl6YWRvcy4KCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQojRmF6ZXIgZ3LDoWZpY28gZGUgbGluaGFzIGNvbSBkYXRhIG5vIGVpeG8gZG8geCBlIG7Dum1lcm8gZGUgY2Fzb3Mgbm8gZWl4byBkbyB5CmNhc29zX2RpYXJpb3NfZ3JhZmljbyA8LSBnZ3Bsb3QoY2Fzb3NfZGlhcmlvcywgYWVzKHggPSBEYXRhLCB5ID0gQ2Fzb3MpKSsKICBnZW9tX3BvaW50KGNvbG9yID0gImNvcmFsMyIsIGFlcyh0ZXh0ID0gcGFzdGUoJ0RhdGE6ICcsIERhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+SW5jaWTDqm5jaWEgOiAnLCBDYXNvcykpKSArCiAgZ2VvbV9saW5lKHNpemUgPSAwLjQsIGNvbG9yID0gImNvcmFsMyIpKwogIGxhYnMoeCA9ICIiKSArCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMikpICsKICBzY2FsZV94X2RhdGUoYnJlYWtzID0gIjMgbW9udGhzIiwgZGF0ZV9sYWJlbHMgPSAiJWIgJWQiKQoKI0ZhemVyIGNvbSBxdWUgZ3LDoWZpY28gc2VqYSBpbnRlcmF0aXZvCmdncGxvdGx5KGNhc29zX2RpYXJpb3NfZ3JhZmljbywgdG9vbHRpcCA9ICJ0ZXh0IikgJT4lIAogIGxheW91dCh5YXhpcyA9IGxpc3QodGl0bGUgPSBwYXN0ZTAoYyhyZXAoIiZuYnNwOyIsIDIwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkluY2lkw6puY2lhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCImbmJzcDsiLCAyMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcCgiXG4mbmJzcDsiLCAyKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xsYXBzZSA9ICIiKSkpCmBgYAoKCiMjIyBBZG1pbmlzdHJhw6fDo28gUmVnaW9uYWwgZGUgU2HDumRlIChBUlMpIHsudGFic2V0fQojIyMjIE7Dum1lcm8gZGUgQ2Fzb3MKPGJyPgpOZXN0ZSBncsOhZmljbyBlIG1hcGEgcG9kZW1vcyB2ZXIgcXVlIExpc2JvYSBlIFZhbGUgZG8gVGVqbyDDqSBhIEFSUyBjb20gbWFpcyBjYXNvcywgc2VndWluZG8tc2UgYSBBUlMgTm9ydGUuIENvbSBtZW5vcyBjYXNvcywgw6kgZGUgcmVhbMOnYXIgb3MgQcOnb3JlcyBlIGEgTWFkZWlyYSBxdWUsIGNvbSBhcyBlc3RyYXTDqWdpYXMgaW1wbGVtZW50YWRhcyBwYXJhIG9zIHR1cmlzdGFzIHF1ZSBvYnJpZ2FtIGEgcmVhbGl6YcOnw6NvIGRlIHVtIHRlc3RlIGFvIFNBUlMtQ29WLTIgbmVnYXRpdm8gYXTDqSA3MmggYW50ZXMgZGEgaWRhIG91IGEgcmVhbGl6YcOnw6NvIGRvIHRlc3RlIMOgIGNoZWdhZGEgYW8gYWVyb3BvcnRvLCBjdW1wcmluZG8gbyBpc29sYW1lbnRvIHByb2ZpbMOhdGljbyBhdMOpIMOgIHJlY2XDp8OjbyBkbyByZXN1bHRhZG8gZG8gbWVzbW8sIGNvbnNlZ3VpcmFtIGxpbWl0YXIgbyBhdW1lbnRvIGRvIG7Dum1lcm8gZGUgY2Fzb3MuIE5vIGVudGFudG8sIHRlbW9zIGRlIHRlciBwcmVzZW50ZSBxdWUgZXN0ZSBncsOhZmljbyBlIG1hcGEgbsOjbyB0w6ptIGVtIGNvbnNpZGVyYcOnw6NvIGEgcG9wdWxhw6fDo28gZGUgY2FkYSBBUlMuCgpgYGB7ciwgd2FybmluZz1GQUxTRX0KI0NyaWFyIHRhYmVsYSBjb20gdW1hIGNvbHVuYSBwYXJhIGEgcmVnacOjbyBlIG91dHJhIHBhcmEgbyB2YWxvciBtYWlzIHJlY2VudGUgZG8gbsO6bWVybyBkZSBjYXNvcyBjb25maXJtYWRvcywgbXVkYXIgbyBub21lIGRhcyBjb2x1bmFzIGUgbXVkYXIgbyBub21lIGRhcyByZWdpw7VlcwpjYXNvc19yZWdpb2VzIDwtIGFzLmRhdGEuZnJhbWUodChhcy5kYXRhLmZyYW1lKGxhcHBseShjb3ZpZDE5cHRbLGNvbmZpcm1hZG9zX2Fyc25vcnRlOmNvbmZpcm1hZG9zX21hZGVpcmFdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXgsIG5hLnJtID0gVFJVRSkpKSklPiUgCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJSZWdpb2VzIikKbmFtZXMoY2Fzb3NfcmVnaW9lcylbMl0gPC0gIkNhc29zIgpjYXNvc19yZWdpb2VzWywgMV0gPC0gYygiTm9ydGUiLCAiQ2VudHJvIiwgIkxWVCIsICJBbGVudGVqbyIsICJBbGdhcnZlIiwgIkHDp29yZXMiLCAiTWFkZWlyYSIpCgojRmF6ZXIgdW0gZ3LDoWZpY28gZGUgYmFycmFzIGNvbSBhcyByZWdpw7VlcyBubyBlaXhvIGRvIHggZSBvIG7Dum1lcm8gZGUgY2Fzb3Mgbm8gZWl4byBkbyB5CmNhc29zX3JlZ2lvZXNfZ3JhZmljbyA8LSBnZ3Bsb3QoY2Fzb3NfcmVnaW9lcywgYWVzKHggPSBSZWdpb2VzLCB5ID0gQ2Fzb3MpKSArCiAgZ2VvbV9jb2woZmlsbCA9ICJzYWxtb24xIiwgd2lkdGggPSAwLjUsIGFlcyh0ZXh0ID0gcGFzdGUoJ0FSUzogJywgUmVnaW9lcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJzxicj5OwrogZGUgQ2Fzb3M6ICcsIENhc29zKSkpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsIDApKSArCiAgbGFicyh4ID0gIiIpICsKICB0aGVtZShheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSkKCmNhc29zX3JlZ2lvZXNfZ3JhZmljb19pbnRlcmF0aXZvIDwtIGdncGxvdGx5KGNhc29zX3JlZ2lvZXNfZ3JhZmljbywgdG9vbHRpcCA9ICJ0ZXh0IikgJT4lIAogICAgbGF5b3V0KHlheGlzID0gbGlzdCh0aXRsZSA9IHBhc3RlMChjKHJlcCgiJm5ic3A7IiwgMjApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTsO6bWVybyBkZSBDYXNvcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcCgiJm5ic3A7IiwgMjApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXAoIlxuJm5ic3A7IiwgMikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sbGFwc2UgPSAiIikpKQoKI21hcGEKIyNEZWZpbmlyIGludGVydmFsb3MgcXVlIHF1ZXJlbW9zIG5hIGxlZ2VuZGEKYmlucyA9ICBjKDAsIDQwMCwgMzAwMCwgMTAwMDAsIDIwMDAwLCA0MDAwMCwgNjAwMDAsIEluZikKCiMjQ29sb2NhciBhcyBSZWdpw6NvZXMgZGEgdGFiZWxhIHBlbGEgbWVzbWEgb3JkZW0gcXVlIGEgZG9zIHBvbGlnb25vcwpjYXNvc19yZWdpb2VzX29yZGVtIDwtIGNhc29zX3JlZ2lvZXNbYyg0LCA1LCA2LCAyLCA3LCAxLCAzKSxdCgojI0RlZmluaXIgYSBwYWxldGUgZGUgY29yZXMgcGFyYSBvIG1hcGEKcGFsIDwtIGNvbG9yQmluKCJZbE9yUmQiLCBkb21haW4gPSBjYXNvc19yZWdpb2VzX29yZGVtWywyXSwgYmlucyA9IGJpbnMpCgojI0RlZmluaXIgbGVnZW5kYSBxdWUgYXBhcmVjZSBxdWFuZG8gc2UgcGFzc2EgbyByYXRvIHBlbG8gbWFwYQpsYWJlbHMgPC0gc3ByaW50ZigKICAiPHN0cm9uZz4lczwvc3Ryb25nPjxici8+JWcgY2Fzb3MiLAogIGNhc29zX3JlZ2lvZXNfb3JkZW1bLDFdLCBjYXNvc19yZWdpb2VzX29yZGVtWywyXQopICU+JSBsYXBwbHkoaHRtbHRvb2xzOjpIVE1MKQoKIyNGYXplciBvIG1hcGEKY2Fzb3NfcmVnaW9lc19tYXBhIDwtIGxlYWZsZXQobWFwYV9wdCkgJT4lIAogIGFkZFRpbGVzKGdyb3VwID0gIk5vcm1hbCIpICU+JSAKICBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVycyRDYXJ0b0RCLlBvc2l0cm9uLCBncm91cCA9ICJDbGFybyIpICU+JSAKICBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVycyRDYXJ0b0RCLkRhcmtNYXR0ZXJOb0xhYmVscywgZ3JvdXAgPSAiRXNjdXJvIikgJT4lIAogIGFkZExheWVyc0NvbnRyb2woCiAgICBiYXNlR3JvdXBzID0gYygiTm9ybWFsIiwgIkNsYXJvIiwgIkVzY3VybyIpLAogICAgb3B0aW9ucyA9IGxheWVyc0NvbnRyb2xPcHRpb25zKGNvbGxhcHNlZCA9IFRSVUUpCiAgKSAlPiUgCiAgYWRkUG9seWdvbnMoCiAgICBmaWxsQ29sb3IgPSB+cGFsKGNhc29zX3JlZ2lvZXNfb3JkZW1bLDJdKSwgCiAgICB3ZWlnaHQgPSAyLAogICAgb3BhY2l0eSA9IDEsCiAgICBjb2xvciA9ICJ3aGl0ZSIsCiAgICBkYXNoQXJyYXkgPSAiMyIsCiAgICBmaWxsT3BhY2l0eSA9IDAuNywKICAgIGhpZ2hsaWdodCA9IGhpZ2hsaWdodE9wdGlvbnMoCiAgICAgIHdlaWdodCA9IDUsCiAgICAgIGNvbG9yID0gIiM2NjYiLAogICAgICBkYXNoQXJyYXkgPSAiIiwKICAgICAgZmlsbE9wYWNpdHkgPSAwLjcsCiAgICAgIGJyaW5nVG9Gcm9udCA9IFRSVUUpLAogICAgbGFiZWwgPSBsYWJlbHMsCiAgICBsYWJlbE9wdGlvbnMgPSBsYWJlbE9wdGlvbnMoc3R5bGUgPSBsaXN0KCJmb250LXdlaWdodCIgPSAibm9ybWFsIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZGRpbmcgPSAiM3B4IDhweCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHRzaXplID0gIjE1cHgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpcmVjdGlvbiA9ICJhdXRvIikpICU+JSAKICBhZGRMZWdlbmQocGFsID0gcGFsLCB2YWx1ZXMgPSBjYXNvc19yZWdpb2VzX29yZGVtJENhc29zLCBvcGFjaXR5ID0gMC43LCB0aXRsZSA9ICJOw7ptZXJvIGRlIENhc29zIHBvciBBUlMiLAogICAgICAgICAgICBwb3NpdGlvbiA9ICJib3R0b21yaWdodCIpCgpicm93c2FibGUoCiAgdGFnTGlzdChsaXN0KAogICAgdGFncyRkaXYoCiAgICAgIHN0eWxlID0gJ3dpZHRoOjUwJTtkaXNwbGF5OmJsb2NrO2Zsb2F0OmxlZnQ7JywKICAgICAgY2Fzb3NfcmVnaW9lc19tYXBhCiAgICApLAogICAgdGFncyRkaXYoCiAgICAgIHN0eWxlID0gJ3dpZHRoOjUwJTtkaXNwbGF5OmJsb2NrO2Zsb2F0OmxlZnQ7JywKICAgICAgY2Fzb3NfcmVnaW9lc19ncmFmaWNvX2ludGVyYXRpdm8KICAgICkKICApKQopCmBgYAoKCiMjIyMgRXZvbHXDp8OjbyBkYSBJbmNpZMOqbmNpYQo8YnI+CkNvbSBhIGludGVycHJldGHDp8OjbyBkZXN0ZSBncsOhZmljbyBkZSBsaW5oYXMsIHBvZGVtb3MgdmVyIHF1ZSBhcyBBUlNzIGRvIE5vcnRlIGUgZG8gQ2VudHJvIHTDqm0gdGlkbyB1bSBjb21wb3J0YW1lbnRvIHNlbWVsaGFudGUuIEFtYmFzIHRpdmVyYW0gdW0gZ3JhbmRlIGF1bWVudG8gZW0gYWJyaWwsIHRlbmRvLXNlIG1hbnRpZG8gZXN0w6F2ZWlzIGR1cmFudGUgb3MgbWVzZXMgZGUgdmVyw6NvLCBjb21lw6dhbmRvIGEgYXVtZW50YXIgZGUgbm92byBlbSBzZXRlbWJyby4gTm8gZW50YW50bywgw6kgaW1wb3J0YW50ZSByZWFsw6dhciBxdWUgbm8gaW7DrWNvIGRhIHBhbmRlbWlhIGEgQVJTIGRvIE5vcnRlIGFwcmVzZW50b3UgdW0gbsO6bWVybyBkZSBub3ZvcyBjYXNvcyBtdWl0byBzdXBlcmlvciBhIHRvZGFzIGFzIG91dHJhcyBBUlNzLCBwb2lzIGZvaSBvbmRlIHN1cmdpcmFtIG9zIHByaW1laXJvcyBzdXJ0b3MgZGVzdGUgdsOtcnVzIGVtIFBvcnR1Z2FsLgoKQSBBUlMgZGUgTGlzYm9hIGUgVmFsZSBkbyBUZWpvLCBwb3Igb3V0cm8gbGFkbywgbsOjbyBhcHJlc2VudG91IHRhbnRvcyBjYXNvcyBkacOhcmlvcyBlbSBhYnJpbCBjb21vIGEgQVJTIGRvIE5vcnRlIHRlbmRvIGluaWNpYWRvIG8gY29uZmluYW1lbnRvIGNvbSBtZW5vciBuw7ptZXJvIGRlIGNhc29zLiBFbSBtYWlvLCBjb20gbyBmaW0gZG8gY29uZmluYW1lbnRvLCDDqSBub3TDoXZlbCB1bSBhdW1lbnRvIGNvbnNpZGVyw6F2ZWwgbm8gbsO6bWVybyBkZSBub3ZvcyBjYXNvcyBxdWUgc2UgcHJvbG9uZ291IGF0w6kganVsaG8uIE5vIHZlcsOjbyBhIGluY2lkw6puY2lhIHNvZnJldSB1bSBkZWNyw6lzY2ltbywgcXVlIHBvZGUgc2VyIHJlc3VsdGFkbyBkZSBkZXNsb2Nhw6fDtWVzIHBhcmEgb3V0cmFzIHJlZ2nDtWVzIGR1cmFudGUgbyBwZXLDrW9kbyBkZSBmw6lyaWFzLiBBIHBhcnRpciBzZXRlbWJybywgY29tIG8gZmltIGRhcyBmw6lyaWFzIGUgbyByZWdyZXNzbyDDoHMgZXNjb2xhcyBlIMOgIGF0aXZpZGFkZSBwcm9maXNzaW9uYWwsIGEgaW5jaWTDqm5jaWEgdGVtIHZpbmRvIGEgYXByZXNlbnRhciB2YWxvcmVzIG1haXMgZWxldmFkb3MuCgpSZWxhdGl2YW1lbnRlIMOgcyBBUlNzIGRvIEFsZW50ZWpvIGUgZG8gQWxnYXJ2ZSwgcG9kZW1vcyB2ZXJpZmljYXIgdW0gYXVtZW50byBzaWduaWZpY2F0aXZvIGRvIG7Dum1lcm8gZGUgbm92b3MgY2Fzb3MgYSBwYXJ0aXIgZGUgbWVhZG9zIGRlIGp1bmhvLCBjb3JyZXNwb25kZW50ZSBhbyBwZXLDrW9kbyBkZSBmw6lyaWFzLiBDb21vIGVtIHRvZGFzIGFzIG91dHJhcyBBUlNzIGRlIFBvcnR1Z2FsIGNvbnRpbmVudGFsLCBhIGluY2lkw6puY2lhIHRlbSB2aW5kbyBhIGF1bWVudGFyIGRlc2RlIG8gaW7DrWNpbyBkZSBzZXRlbWJybyBwZWxhcyBtZXNtYXMgcmF6w7VlcyBhcHJlc2VudGFkYXMgYW50ZXJpb3JtZW50ZS4KClF1YW50byBhb3MgQcOnb3JlcyBlIMOgIE1hZGVpcmEsIMOpIG5vdMOhdmVsIGEgYXVzw6puY2lhIHF1YXNlIHRvdGFsIGRlIG5vdm9zIGNhc29zIGR1cmFudGUgb3MgbWVzZXMgZGUgbWFpbyBlIGp1bmhvLCByZXN1bHRhZG8gZGUgdW1hIHRlc3RhZ2VtIG1hc3NpdmEgY29tIGFkZXF1YWRvIGNvbnRyb2xvIGRvcyBjYXNvcyBpbmljaWFpcyBlIGRhIGltcGxlbWVudGHDp8OjbyBkZSBtZWRpZGFzIGNvbnRlbsOnw6NvLCBjb21vIGEgcXVhcmVudGVuYSBvYnJpZ2F0w7NyaWEgZSBwZXJtaXNzw6NvIGRlIGVudHJhZGEgZXhjbHVzaXZhIGEgcmVzaWRlbnRlcy4gQSBwYXJ0aXIgZGUganVsaG8sIHZvbHRhcmFtIGEgc3VyZ2lyIGFsZ3VucyBjYXNvcyBkZXZpZG8gYW8gbGV2YW50YW1lbnRvIGRhIHJlc3RyacOnw6NvIMOgIGVudHJhZGEgZGUgdHVyaXN0YXMuIMOJIHRhbWLDqW0gZGUgcmVhbMOnYXIgcXVlIHPDo28gYXMgw7puaWNhcyByZWdpw7VlcyBxdWUgbsOjbyB0w6ptIHNvZnJpZG8gdW0gYXVtZW50byBkZXNkZSBzZXRlbWJyby4gCgpgYGB7ciwgd2FybmluZz1GQUxTRX0KI0ZhemVyIHRhYmVsYSBjb20gbsO6bWVybyBkZSBjYXNvcyBkacOhcmlvcyBwb3IgcmVnacOjbwppbmNpZGVuY2lhX3JlZ2lvZXNfdGVtcG8gPC0gY2JpbmQoY292aWQxOXB0JGRhdGEsIChhcy5kYXRhLmZyYW1lKGNvdmlkMTlwdFssIGNvbmZpcm1hZG9zX2Fyc25vcnRlOmNvbmZpcm1hZG9zX21hZGVpcmFdIC1sYWcoY292aWQxOXB0Wyxjb25maXJtYWRvc19hcnNub3J0ZTpjb25maXJtYWRvc19tYWRlaXJhXSkpKSkKbmFtZXMoaW5jaWRlbmNpYV9yZWdpb2VzX3RlbXBvKSA9ICBjKCJEYXRhIiwgIk5vcnRlIiwgIkNlbnRybyIsICJMVlQiLCAiQWxlbnRlam8iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBbGdhcnZlIiwgIkHDp29yZXMiLCAiTWFkZWlyYSIpCmluY2lkZW5jaWFfcmVnaW9lc190ZW1wb19tZWx0IDwtIG1lbHQoaW5jaWRlbmNpYV9yZWdpb2VzX3RlbXBvLCBpZC52YXJzID0gIkRhdGEiKQpuYW1lcyhpbmNpZGVuY2lhX3JlZ2lvZXNfdGVtcG9fbWVsdCkgPSBjKCJEYXRhIiwgIlJlZ2lhbyIsICJJbmNpZGVuY2lhIikKCiNGYXplciBncsOhZmljbyBkZSBsaW5oYXMgY29tIGRhdGEgbm8gZWl4byBkbyB4LCBhIGluY2lkZW5jaWEgbm8gZWl4byBkbyB5IGUgbyBnw6luZXJvIGVtIGNhZGEgbGluaGEKaW5jaWRlbmNpYV9yZWdpb2VzX3RlbXBvX2dyYWZpY28gPC0gZ2dwbG90KGluY2lkZW5jaWFfcmVnaW9lc190ZW1wb19tZWx0LCBhZXMoeCA9IERhdGEsIHkgPSBJbmNpZGVuY2lhLCBjb2xvciA9IFJlZ2lhbykpICsKICBnZW9tX3BvaW50KGFlcyh0ZXh0ID0gcGFzdGUoJ0RhdGE6ICcsIERhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+QVJTOiAnLCBSZWdpYW8sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+SW5jaWTDqm5jaWE6ICcsIEluY2lkZW5jaWEpKSwgc2l6ZSA9IDAuMSkgKwogIGdlb21fbGluZShzaXplID0gMC41KSArCiAgbGFicyh4ID0gIiIpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogIHNjYWxlX3hfZGF0ZShicmVha3MgPSAiMyBtb250aHMiLCBkYXRlX2xhYmVscyA9ICIlYiAlZCIpCgojVG9ybmFyIGludGVyYXRpdm8KaW5jaWRlbmNpYV9yZWdpb2VzX3RlbXBvX2dyYWZpY29faW50ZXJhdGl2byA8LSBnZ3Bsb3RseShpbmNpZGVuY2lhX3JlZ2lvZXNfdGVtcG9fZ3JhZmljbywgdG9vbHRpcCA9ICJ0ZXh0IikgJT4lIAogICAgbGF5b3V0KHlheGlzID0gbGlzdCh0aXRsZSA9IHBhc3RlMChjKHJlcCgiJm5ic3A7IiwgMjApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSW5jaWTDqm5jaWEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXAoIiZuYnNwOyIsIDIwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCJcbiZuYnNwOyIsIDIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlID0gIiIpKSkKCiNJbmNpZMOqbmNpYSBjb20gbcOpZGlhIHJvbGFudGUgNyBkaWFzCiMjRmF6ZXIgYSBtw6lkaWEgcm9sYW50ZQppbmNpZGVuY2lhX3JlZ2lvZXNfdGVtcG9fbWVkaWFfcm9sYW50ZSA8LSBjYmluZChpbmNpZGVuY2lhX3JlZ2lvZXNfdGVtcG9bNzpucm93KGluY2lkZW5jaWFfcmVnaW9lc190ZW1wbyksMV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLmRhdGEuZnJhbWUocm9sbG1lYW4oaW5jaWRlbmNpYV9yZWdpb2VzX3RlbXBvWywyOjhdLCBrID0gNykpKQpuYW1lcyhpbmNpZGVuY2lhX3JlZ2lvZXNfdGVtcG9fbWVkaWFfcm9sYW50ZSlbMV0gPSAiRGF0YSIKCmluY2lkZW5jaWFfcmVnaW9lc190ZW1wb19tZWRpYV9yb2xhbnRlX21lbHQgPC0gbWVsdChpbmNpZGVuY2lhX3JlZ2lvZXNfdGVtcG9fbWVkaWFfcm9sYW50ZSwgaWQudmFycyA9ICJEYXRhIikKbmFtZXMoaW5jaWRlbmNpYV9yZWdpb2VzX3RlbXBvX21lZGlhX3JvbGFudGVfbWVsdCkgPSBjKCJEYXRhIiwgIlJlZ2lhbyIsICJJbmNpZGVuY2lhIikKCiMjRmF6ZXIgZ3LDoWZpY28KaW5jaWRlbmNpYV9yZWdpb2VzX3RlbXBvX21lZGlhX3JvbGFudGVfbWVsdF9ncmFmaWNvIDwtIGdncGxvdChpbmNpZGVuY2lhX3JlZ2lvZXNfdGVtcG9fbWVkaWFfcm9sYW50ZV9tZWx0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IERhdGEsIHkgPSBJbmNpZGVuY2lhLCBjb2xvciA9IFJlZ2lhbykpICsKICBnZW9tX3BvaW50KGFlcyh0ZXh0ID0gcGFzdGUoJ0RhdGE6ICcsIERhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+QVJTOiAnLCBSZWdpYW8sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+SW5jaWTDqm5jaWE6ICcsIEluY2lkZW5jaWEpKSwgc2l6ZSA9IDAuMSkgKwogIGdlb21fbGluZShzaXplPTAuNSkgKwogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcpKSArCiAgbGFicyh0aXRsZSA9ICJNw6lkaWEgUm9sYW50ZSAoNyBkaWFzKSIsCiAgICAgICB4ID0gIiIsCiAgICAgICB5ID0gIkluY2lkw6puY2lhIikgKwogIHNjYWxlX3hfZGF0ZShicmVha3MgPSAiMyBtb250aHMiLCBkYXRlX2xhYmVscyA9ICIlYiAlZCIpCgojI1Rvcm5hciBncsOhZmljbyBpbnRlcmF0aXZvCmluY2lkZW5jaWFfcmVnaW9lc190ZW1wb19tZWRpYV9yb2xhbnRlX21lbHRfZ3JhZmljb19pbnRlcmF0aXZvIDwtIGdncGxvdGx5KGluY2lkZW5jaWFfcmVnaW9lc190ZW1wb19tZWRpYV9yb2xhbnRlX21lbHRfZ3JhZmljbywgdG9vbHRpcCA9ICJ0ZXh0IikgJT4lIAogIGxheW91dCh5YXhpcyA9IGxpc3QodGl0bGUgPSBwYXN0ZTAoYyhyZXAoIiZuYnNwOyIsIDIwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkluY2lkw6puY2lhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCImbmJzcDsiLCAyMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcCgiXG4mbmJzcDsiLCAyKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xsYXBzZSA9ICIiKSksCiAgICAgICAgIGxlZ2VuZCA9IGxpc3QoeCA9IDEsIHkgPSAwKSkKCgojbWFwYQojI0ZhemVyIHRhYmVsYSBjb20gbm92b3MgY2Fzb3MgbWFpcyByZWNlbnRlcwppbmNpZGVuY2lhX3JlZ2lvZXNfcmVjZW50ZSA8LSBhcy5kYXRhLmZyYW1lKHQoYXMuZGF0YS5mcmFtZSgKICBsYXBwbHkoKGNvdmlkMTlwdFssIGNvbmZpcm1hZG9zX2Fyc25vcnRlOmNvbmZpcm1hZG9zX21hZGVpcmFdKQogICAgICAgICAtIGxhZyhjb3ZpZDE5cHRbLCBjb25maXJtYWRvc19hcnNub3J0ZTpjb25maXJtYWRvc19tYWRlaXJhXSksIGxhc3QpKSkpICU+JSAKICByb3duYW1lc190b19jb2x1bW4odmFyID0gIlJlZ2lvZXMiKQppbmNpZGVuY2lhX3JlZ2lvZXNfcmVjZW50ZVssMV0gPSBjKCJOb3J0ZSIsICJDZW50cm8iLCAiTGlzYm9hIGUgVmFsZSBkbyBUZWpvIiwgIkFsZW50ZWpvIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFsZ2FydmUiLCAiQcOnb3JlcyIsICJNYWRlaXJhIikKCiMjRGVmaW5pciBpbnRlcnZhbG9zIHBhcmEgbGVnZW5kYQpiaW5zXzcgPSAgYygwLCA1MCwgMzAwLCA1MDAsIDgwMCwgMTAwMCwgMTUwMCwgMjAwMCwgSW5mKQoKIyNEZWZpbmlyIHBhbGV0ZSBkZSBjb3JlcyBwYXJhIG1hcGEKcGFsXzcgPC0gY29sb3JCaW4oIllsT3JSZCIsIGRvbWFpbiA9IGluY2lkZW5jaWFfcmVnaW9lc19yZWNlbnRlWywyXSwgYmlucyA9IGJpbnNfNykKCiMjRGEgdGFiZWxhIGFudGVyaW9yIGNvbSB0b2RhcyBhcyBkYXRhcywgc2VsZWNpb25hciBhcGVuYXMgbyB2YWxvciBtYWlzIHJlY2VudGUgZSBtdWRhciBub21lIGNvbHVuYSBlIFJlZ2nDo29lcwppbmNpZGVuY2lhX3JlZ2lvZXNfcmVjZW50ZSA8LSBpbmNpZGVuY2lhX3JlZ2lvZXNfcmVjZW50ZVtjKDQsIDUsIDYsIDIsIDcsIDEsIDMpLF0gCgojI0RlZmluaXIgbGVnZW5kYSBxdWFuZG8gc2UgcGFzc2EgY29tIG8gcmF0byBwb3IgY2ltYQpsYWJlbHNfNyA8LSBzcHJpbnRmKAogICI8c3Ryb25nPiVzPC9zdHJvbmc+PGJyLz4lZyBjYXNvcyBub3ZvcyIsCiAgaW5jaWRlbmNpYV9yZWdpb2VzX3JlY2VudGVbLDFdLCByb3VuZChpbmNpZGVuY2lhX3JlZ2lvZXNfcmVjZW50ZVssMl0sIGRpZ2l0cyA9IDQpCikgJT4lIGxhcHBseShodG1sdG9vbHM6OkhUTUwpCgoKIyNGYXplciBvIG1hcGEKaW5jaWRlbmNpYV9yZWdpb2VzX21hcGEgPC0gbGVhZmxldChtYXBhX3B0KSAlPiUgCiAgYWRkVGlsZXMoZ3JvdXAgPSAiTm9ybWFsIikgJT4lIAogIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJENhcnRvREIuUG9zaXRyb24sIGdyb3VwID0gIkNsYXJvIikgJT4lIAogIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJENhcnRvREIuRGFya01hdHRlck5vTGFiZWxzLCBncm91cCA9ICJFc2N1cm8iKSAlPiUgCiAgYWRkTGF5ZXJzQ29udHJvbCgKICAgIGJhc2VHcm91cHMgPSBjKCJOb3JtYWwiLCAiQ2xhcm8iLCAiRXNjdXJvIiksCiAgICBvcHRpb25zID0gbGF5ZXJzQ29udHJvbE9wdGlvbnMoY29sbGFwc2VkID0gVFJVRSkKICApICU+JSAKICBhZGRQb2x5Z29ucygKICAgIGZpbGxDb2xvciA9IH5wYWxfNyhpbmNpZGVuY2lhX3JlZ2lvZXNfcmVjZW50ZVssMl0pLCAKICAgIHdlaWdodCA9IDIsCiAgICBvcGFjaXR5ID0gMSwKICAgIGNvbG9yID0gIndoaXRlIiwKICAgIGRhc2hBcnJheSA9ICIzIiwKICAgIGZpbGxPcGFjaXR5ID0gMC43LAogICAgaGlnaGxpZ2h0ID0gaGlnaGxpZ2h0T3B0aW9ucygKICAgICAgd2VpZ2h0ID0gNSwKICAgICAgY29sb3IgPSAiIzY2NiIsCiAgICAgIGRhc2hBcnJheSA9ICIiLAogICAgICBmaWxsT3BhY2l0eSA9IDAuNywKICAgICAgYnJpbmdUb0Zyb250ID0gVFJVRSksCiAgICBsYWJlbCA9IGxhYmVsc183LAogICAgbGFiZWxPcHRpb25zID0gbGFiZWxPcHRpb25zKHN0eWxlID0gbGlzdCgiZm9udC13ZWlnaHQiID0gIm5vcm1hbCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWRkaW5nID0gIjNweCA4cHgiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0c2l6ZSA9ICIxNXB4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXJlY3Rpb24gPSAiYXV0byIpKSAlPiUgCiAgYWRkTGVnZW5kKHBhbCA9IHBhbF83LCB2YWx1ZXMgPSBpbmNpZGVuY2lhX3JlZ2lvZXNfcmVjZW50ZVssMl0sIG9wYWNpdHkgPSAwLjcsIHRpdGxlID0gIkluY2lkw6puY2lhIEF0dWFsIHBvciBBUlMiLAogICAgICAgICAgICBwb3NpdGlvbiA9ICJib3R0b21yaWdodCIpCgojSW5jaWTDqm5jaWEgY29tIG3DqWRpYSByb2xhbnRlIDE0IGRpYXMKIyNGYXplciBhIG3DqWRpYSByb2xhbnRlCmluY2lkZW5jaWFfcmVnaW9lc190ZW1wb19tZWRpYV9yb2xhbnRlXzE0IDwtIGNiaW5kKGluY2lkZW5jaWFfcmVnaW9lc190ZW1wb1sxNDpucm93KGluY2lkZW5jaWFfcmVnaW9lc190ZW1wbyksMV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLmRhdGEuZnJhbWUocm9sbG1lYW4oaW5jaWRlbmNpYV9yZWdpb2VzX3RlbXBvWywyOjhdLCBrID0gMTQpKSkKbmFtZXMoaW5jaWRlbmNpYV9yZWdpb2VzX3RlbXBvX21lZGlhX3JvbGFudGVfMTQpWzFdID0gIkRhdGEiCgppbmNpZGVuY2lhX3JlZ2lvZXNfdGVtcG9fbWVkaWFfcm9sYW50ZV8xNF9tZWx0IDwtIG1lbHQoaW5jaWRlbmNpYV9yZWdpb2VzX3RlbXBvX21lZGlhX3JvbGFudGVfMTQsIGlkLnZhcnMgPSAiRGF0YSIpCm5hbWVzKGluY2lkZW5jaWFfcmVnaW9lc190ZW1wb19tZWRpYV9yb2xhbnRlXzE0X21lbHQpID0gYygiRGF0YSIsICJSZWdpYW8iLCAiSW5jaWRlbmNpYSIpCgojI0ZhemVyIGdyw6FmaWNvCmluY2lkZW5jaWFfcmVnaW9lc190ZW1wb19tZWRpYV9yb2xhbnRlXzE0X21lbHRfZ3JhZmljbyA8LSBnZ3Bsb3QoaW5jaWRlbmNpYV9yZWdpb2VzX3RlbXBvX21lZGlhX3JvbGFudGVfMTRfbWVsdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBEYXRhLCB5ID0gSW5jaWRlbmNpYSwgY29sb3IgPSBSZWdpYW8pKSArCiAgZ2VvbV9wb2ludChhZXModGV4dCA9IHBhc3RlKCdEYXRhOiAnLCBEYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnPGJyPkFSUzogJywgUmVnaWFvLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnPGJyPkluY2lkw6puY2lhOiAnLCBJbmNpZGVuY2lhKSksIHNpemUgPSAwLjEgKSArCiAgZ2VvbV9saW5lKHNpemU9MC41KSArCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gNykpICsKICBsYWJzKHRpdGxlID0gIk3DqWRpYSBSb2xhbnRlICgxNCBkaWFzKSIsCiAgICAgICB4ID0gIiIsCiAgICAgICB5ID0gIkluY2lkw6puY2lhIikgKwogIHNjYWxlX3hfZGF0ZShicmVha3MgPSAiMyBtb250aHMiLCBkYXRlX2xhYmVscyA9ICIlYiAlZCIpCgojI1Rvcm5hciBncsOhZmljbyBpbnRlcmF0aXZvCmluY2lkZW5jaWFfcmVnaW9lc190ZW1wb19tZWRpYV9yb2xhbnRlXzE0X21lbHRfZ3JhZmljb19pbnRlcmF0aXZvIDwtIGdncGxvdGx5KGluY2lkZW5jaWFfcmVnaW9lc190ZW1wb19tZWRpYV9yb2xhbnRlXzE0X21lbHRfZ3JhZmljbywgdG9vbHRpcCA9ICJ0ZXh0IikgJT4lIAogIGxheW91dCh5YXhpcyA9IGxpc3QodGl0bGUgPSBwYXN0ZTAoYyhyZXAoIiZuYnNwOyIsIDIwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkluY2lkw6puY2lhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCImbmJzcDsiLCAyMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcCgiXG4mbmJzcDsiLCAyKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xsYXBzZSA9ICIiKSksCiAgICAgICAgIGxlZ2VuZCA9IGxpc3QoeCA9IDEsIHkgPSAwKSkKCgpicm93c2FibGUoCiAgdGFnTGlzdChsaXN0KAogICAgdGFncyRkaXYoCiAgICAgIHN0eWxlID0gJ3dpZHRoOjUwJTtkaXNwbGF5OmJsb2NrO2Zsb2F0OmxlZnQ7JywKICAgICAgaW5jaWRlbmNpYV9yZWdpb2VzX3RlbXBvX2dyYWZpY29faW50ZXJhdGl2bwogICAgKSwKICAgIHRhZ3MkZGl2KAogICAgICBzdHlsZSA9ICd3aWR0aDo1MCU7ZGlzcGxheTpibG9jaztmbG9hdDpsZWZ0OycsCiAgICAgIGluY2lkZW5jaWFfcmVnaW9lc190ZW1wb19tZWRpYV9yb2xhbnRlX21lbHRfZ3JhZmljb19pbnRlcmF0aXZvCiAgICApCiAgKSkKKQoKCmJyb3dzYWJsZSgKICB0YWdMaXN0KGxpc3QoCiAgICB0YWdzJGRpdigKICAgICAgc3R5bGUgPSAnd2lkdGg6NTAlO2Rpc3BsYXk6YmxvY2s7ZmxvYXQ6bGVmdDsnLAogICAgICBpbmNpZGVuY2lhX3JlZ2lvZXNfdGVtcG9fbWVkaWFfcm9sYW50ZV8xNF9tZWx0X2dyYWZpY29faW50ZXJhdGl2bwogICAgKSwKICAgIHRhZ3MkZGl2KAogICAgICBzdHlsZSA9ICd3aWR0aDo1MCU7ZGlzcGxheTpibG9jaztmbG9hdDpsZWZ0OycsCiAgICAgIGluY2lkZW5jaWFfcmVnaW9lc19tYXBhCiAgICApCiAgKSkKKQoKCmBgYAoKCiMjIyMgRXZvbHXDp8OjbyBkYSBUYXhhIGRlIEluY2lkw6puY2lhCjxicj4KQ29tIGVzdGUgZ3LDoWZpY28gZGUgbGluaGFzIGNvbnNlZ3VpbW9zIHZlciBhIGV2b2x1w6fDo28gdGVtcG9yYWwgZGFzIGRpZmVyZW50ZXMgdGF4YXMgZGUgaW5jaWTDqm5jaWEgcGFyYSBjYWRhIEFSUy4gCgpBcyByZWdpw7VlcyBkb3MgQcOnb3JlcyBlIGRhIE1hZGVpcmEgc8OjbyBhcyBxdWUgdMOqbSBhcyB0YXhhcyBkZSBpbmNpZMOqbmNpYSBtYWlzIGJhaXhhcyBlIG1haXMgY29uc3RhbnRlcy4gCgpBcyBBUlNzIGRvIEFsZ2FydmUgZSBkbyBBbGVudGVqbyB0w6ptIHVtIGNvbXBvcnRhbWVudG8gbXVpdG8gc2VtZWxoYW50ZSBlbnRyZSBzaS4gVGl2ZXJhbSB1bSBhdW1lbnRvIGVtIGFicmlsLCBjb21vIHRvZGFzIGFzIG91dHJhcyBBUlNzLCBzb2ZyZW5kbyB1bWEgZGltaW51acOnw6NvIHBvc3Rlcmlvcm1lbnRlIGUgbWFudGVuZG8tc2UgY29uc3RhbnRlcyBhdMOpIGFvIGluw61jbyBkbyB2ZXLDo28uIENvbW8gcG9kZW1vcyB2ZXIsIG5lc3RhcyBkdWFzIEFSU3MgbXVpdG8gcHJvY3VyYWRhcyBjb21vIGRlc3Rpbm8gZGUgZsOpcmlhcywgYXMgdGF4YXMgZGUgaW5jaWTDqm5jaWEgYXVtZW50YXJhbSBsb2dvIGEgcGFydGlyIGRlIGp1bmhvLiBDb250dWRvLCBhIEFSUyBkbyBBbGVudGVqbyBtb3N0cmEgYWxndW5zIHBpY29zIG5vIHZlcsOjbyBxdWUgcG9kZW0gc2VyIHJlZmVyZW50ZXMgYW9zIHN1cnRvcyBlbSBsYXJlcy4KCkEgQVJTIGRvIENlbnRybyDDqSwgZGFzIEFSU3MgZGUgUG9ydHVnYWwgY29udGluZW50YWwsIGEgw7puaWNhIHF1ZSBzZSB0ZW0gbWFudGlkbyBjb25zdGFudGUgZGVzdGUgc2V0ZW1icm8sIHNlbSBncmFuZGVzIHZhcmlhw6fDtWVzLgoKQSBBUlMgZG8gTm9ydGUgZm9pIGEgcXVlIHRldmUgdW1hIG1haW9yIHRheGEgZGUgaW5jaWTDqm5jaWEgZW0gYWJyaWwsIHRlbmRvIGVzdGFiaWxpemFkbyBlbSBtZWFkb3MgZGUgbWFpby4gRGVzZGUgc2V0ZW1icm8gdm9sdG91IGEgc3ViaXIgZGUgZm9ybWEgY29uc2lkZXLDoXZlbC4gCgpBIEFSUyBkZSBMaXNib2EgZSBWYWxlIGRvIFRlam8gw6kgYSBxdWUgdGVtIG8gY29tcG9ydGFtZW50byBtYWlzIGTDrXNwYXIgZSBwcmVvY3VwYW50ZS4gU2VtIG51bmNhIHRlciBkaW1pbnXDrWRvIGEgdGF4YSBkZSBpbmNpZMOqbmNpYSBkZSBmb3JtYSB0w6NvIGFjZW50dWFkYSBjb21vIGFzIG91dHJhcyBBUlNzLCBtYW50ZXZlLXNlIGNvbSBvc2NpbGHDp8O1ZXMgcmVjb3JyZW50ZXMgYW8gbG9uZ28gZG8gdmVyw6NvLiBFc3RhIGNvbWXDp291IGEgc3ViaXIgYSBwYXJ0aXIgZGUgc2V0ZW1icm8sIGFwcmVzZW50YW5kbyBvIG1haW9yIHZhbG9yIGRlc2RlIG8gaW7DrWNpbyBkYSBwYW5kZW1pYS4KCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQojVmFsb3JlcyBkYSBwb3B1bGHDp8OjbyBkZSBjYWRhIFJlZ2nDo28gY29tIGJhc2UgbmFzIENDRFJzCmFjb3JlcyA9IDI0Mjc5NgphbGVudGVqbyA9IDUwMzUwNwphbGdhcnZlID0gNDUwNDg0CmNlbnRybyA9IDIyMTcyODUKbGlzYm9hID0gMzYzMTczOAptYWRlaXJhID0gMjUzOTQ1Cm5vcnRlID0gMzU3NTMzOAoKI0NyaWFyIHVtYSB0YWJlbGEgY29tIHVtYSBjb2x1bmEgcGFyYSBhcyBSZWdpw6NvZXMgZSBvdXRyYSBwYXJhIG8gbsO6bWVybyBkZSBwZXNzb2FzIG5lc3NhIFJlZ2nDo28KcG9wdWxhY2FvX3JlZ2lvZXMgPC0gYXMuZGF0YS5mcmFtZShjKG5vcnRlLCBjZW50cm8sIGxpc2JvYSwgYWxlbnRlam8sIGFsZ2FydmUsIGFjb3JlcywgbWFkZWlyYSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoIm5vcnRlIiwgImNlbnRybyIsICJsaXNib2EiLCAiYWxlbnRlam8iLCAiYWxnYXJ2ZSIsICJhw6dvcmVzIiwgIm1hZGVpcmEiKSkKY29sbmFtZXMocG9wdWxhY2FvX3JlZ2lvZXMpIDwtICJQb3B1bGHDp8OjbyIKCiMjI0ZhemVyIGNvbSBxdWUgY2FkYSBjb2x1bmEgc2VqYSB1bWEgUmVnacOjbyBlIHJlcGV0aXIgY2FkYSBuw7ptZXJvIGFzIHZlemVzIG5lY2Vzc8OhcmlhcyBwYXJhIGZpY2FyIGNvbSBvIG7Dum1lcm8gaWd1YWwgYW8gZGFzIGNvbHVuYXMgZGEgYmFzZSBkZSBkYWRvcwpwb3B1bGFjYW9fcmVnaW9lc19yZXAgPC0gYXMuZGF0YS5mcmFtZSh0KHBvcHVsYWNhb19yZWdpb2VzW3JlcChzZXFfbGVuKG5jb2wocG9wdWxhY2FvX3JlZ2lvZXMpKSwgZWFjaCA9IG5yb3coY292aWQxOXB0KSldKSkKCiMjI0NhbGN1bGFyIGEgaW5jaWTDqm5jaWEgZW0gY2FkYSBSZWdpw6NvIGZhemVuZG8gb3MgY2Fzb3Mgbm92b3MgcG9yIFJlZ2nDo28gYSBkaXZpZGlyIHBlbGEgcG9wdWxhw6fDo28gZGEgUmVnacOjbyBtZW5vcyBvcyBjb25maXJtYWRvcyBkYSBSZWdpw6NvIG1lbm9zIG9zIMOzYml0b3MgZGEgUmVnacOjbyBlIGRhciBub21lcyBhIGNhZGEgY29sdW5hCmluY2lkZW5jaWFfcmVnaW9lcyA8LSBjYmluZChjb3ZpZDE5cHQkZGF0YSwgKGFzLmRhdGEuZnJhbWUoY292aWQxOXB0WywgY29uZmlybWFkb3NfYXJzbm9ydGU6Y29uZmlybWFkb3NfbWFkZWlyYV0gCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0gbGFnKGNvdmlkMTlwdFssIGNvbmZpcm1hZG9zX2Fyc25vcnRlOmNvbmZpcm1hZG9zX21hZGVpcmFdKSkpIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgLyAocG9wdWxhY2FvX3JlZ2lvZXNfcmVwIC0gYXMuZGF0YS5mcmFtZShjb3ZpZDE5cHRbLGNvbmZpcm1hZG9zX2Fyc25vcnRlOmNvbmZpcm1hZG9zX21hZGVpcmFdKSkpCm5hbWVzKGluY2lkZW5jaWFfcmVnaW9lcykgPC0gYygiRGF0YSIsICJOb3J0ZSIsICJDZW50cm8iLCAiTGlzYm9hIGUgVmFsZSBkbyBUZWpvIiwgIkFsZW50ZWpvIiwgIkFsZ2FydmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkHDp29yZXMiLCAiTWFkZWlyYSIpCgojIyNGYXplciBtZWx0IHBhcmEgZmF6ZXIgbyBncsOhZmljbyBlIGRhciBub21lcyBhIGNhZGEgY29sdW5hCmluY2lkZW5jaWFfcmVnaW9lc19tZWx0IDwtIG1lbHQoaW5jaWRlbmNpYV9yZWdpb2VzLCBpZC52YXJzID0gIkRhdGEiKQpuYW1lcyhpbmNpZGVuY2lhX3JlZ2lvZXNfbWVsdCkgPC0gYygiZGF0YSIsICJyZWdpYW8iLCAidmFsb3IiKQoKIyMjRmF6ZXIgbyBncsOhZmljbyBkZSBsaW5oYXMgY29tIGEgZGF0YSBubyBlaXhvIGRvIHgsIGEgaW5jaWTDqm5jaWEgbm8gZWl4byBkbyB5IGUgYSBSZWdpw6NvIGVtIGNhZGEgbGluaGEKZ2dwbG90KGluY2lkZW5jaWFfcmVnaW9lc19tZWx0LCBhZXMoeCA9IGRhdGEsIHkgPSB2YWxvcioxMDAsIGNvbG9yID0gcmVnaWFvKSkgKwogIGdlb21fbGluZSgpICsgCiAgbGFicyh4ID0gIiIsIAogICAgICAgeSA9ICJUYXhhIGRlIEluY2lkw6puY2lhICglKSIpICsKICBmYWNldF9ncmlkKGluY2lkZW5jaWFfcmVnaW9lc19tZWx0JHJlZ2lhbykgKwogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4odCA9IDE1LCBiID0gMTApLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKHIgPSAxNSwgbCA9IDEwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxMiksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDUpLAogICAgICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCwgYW5nbGUgPSAwKSkgKwogIGd1aWRlcyhjb2xvciA9IEZBTFNFKSArCiAgc2NhbGVfeF9kYXRlKGJyZWFrcyA9ICIzIG1vbnRocyIsIGRhdGVfbGFiZWxzID0gIiViICVkIikKYGBgCgojIyMjIFRheGEgZGUgSW5jaWTDqm5jaWEgQ3VtdWxhdGl2YQo8YnI+CkNvbW8gw6kgcG9zc8OtdmVsIHZlcmlmaWNhciBjb20gYSBhbsOhbGlzZSBkZXN0ZSBncsOhZmljbyBkZSBiYXJyYXMgZSBtYXBhLCBhcyBBUlNzIGRlIExpc2JvYSBlIFZhbGUgZG8gVGVqbyBlIGRvIE5vcnRlIGFwcmVzZW50YW0gdmFsb3JlcyBkZSBwcmV2YWzDqm5jaWEgYmFzdGFudGUgc3VwZXJpb3JlcyDDoHMgb3V0cmFzIEFSU3MuIERlc3RhIGZvcm1hLCBjb25jbHXDrW1vcyBxdWUsIGFwZXNhciBkZSBzZXJlbSBhcyBBUlNzIGNvbSBtYWlvciBwb3B1bGHDp8OjbywgbsOjbyDDqSBlc3RlIGZhdG9yIHF1ZSBqdXN0aWZpY2EgZGlyZXRhbWVudGUgbyBlbGV2YWRvIG7Dum1lcm8gZGUgY2Fzb3MuCgpSZWxhdGl2YW1lbnRlIMOgcyBBUlNzIGRvIEFsZ2FydmUgZSBkbyBBbGVudGVqbywgYXBlc2FyIGRlIHNlcmVtIGFzIEFSU3MgY29tIG1lbm9yIHBvcHVsYcOnw6NvIGRlIFBvcnR1Z2FsIGNvbnRpbmVudGFsLCB0w6ptIGFzIHRlcmNlaXJhcyBlIHF1YXJ0YXMgcHJldmFsw6puY2lhcyBtYWlzIGVsZXZhZGFzLCByZXNwZXRpdmFtZW50ZS4gSXN0byBwb2RlIHNlciBqdXN0aWZpY2FkbyBwZWxvIGZhY3RvIGRlIGFtYmFzIGFzIEFSU3Mgc2VyZW0gZGVzdGlub3MgZGUgZWxlacOnw6NvIGRlIGbDqXJpYXMsIHRlbmRvIHNvZnJpZG8gdW0gYXVtZW50byBkYSBpbmNpZMOqbmNpYSBkdXJhbnRlIG8gdmVyw6NvIChncsOhZmljbyBkYSBFdm9sdcOnw6NvIGRhIEluY2lkw6puY2lhIHBvciBBUlMpLiBPIGZhY3RvIGRlIG9zIHR1cmlzdGFzIG7Do28gc2VyZW0gY29udGFiaWxpemFkb3MgbmEgcG9wdWxhw6fDo28gZGVzdGFzIEFSU3MsIGNvbnRyaWJ1aSBwYXJhIG8gYXVtZW50byBkYSBwcmV2YWzDqm5jaWEgKGlzdG8gc2UgbyB0dXJpc3RhIGZvciBjb25zaWRlcmFkbyBjb25maXJtYWRvIG5hIEFSUyBvbmRlIHRlc3RvdSBwb3NpdGl2bykuCgpDb21vIHJlZmVyaWRvIGFudGVyaW9ybWVudGUsIGFzIGJhaXhhcyBwcmV2YWzDqm5jaWFzIGRvcyBBw6dvcmVzIGUgZGEgTWFkZWlyYSBjb25maXJtYW0gbyBzdWNlc3NvIGRhcyBtZWRpZGFzIGltcGxlbWVudGFkYXMuIAoKYGBge3IsIHdhcm5pbmc9RkFMU0V9CnBvcHVsYWNhb19yZWdpb2VzX2ludmVydGlkbyA8LSB0KHBvcHVsYWNhb19yZWdpb2VzKQoKcHJldmFsZW5jaWFfcmVnaWFvIDwtIChhcy5kYXRhLmZyYW1lKHQoYXMuZGF0YS5mcmFtZSgobGFwcGx5KGNvdmlkMTlwdFssY29uZmlybWFkb3NfYXJzbm9ydGU6Y29uZmlybWFkb3NfbWFkZWlyYV0sIGxhc3QpKSkpKSoxMDAgLyBwb3B1bGFjYW9fcmVnaW9lc19pbnZlcnRpZG8pICU+JSAKICByb3duYW1lc190b19jb2x1bW4odmFyPSJSZWdpYW8iKQpjb2xuYW1lcyhwcmV2YWxlbmNpYV9yZWdpYW8pWzJdIDwtICJQcmV2YWxlbmNpYSIKcHJldmFsZW5jaWFfcmVnaWFvWywxXSA8LSBjKCJOb3J0ZSIsICJDZW50cm8iLCAiTFZUIiwgIkFsZW50ZWpvIiwgIkFsZ2FydmUiLCAiQcOnb3JlcyIsICJNYWRlaXJhIikKCnByZXZhbGVuY2lhX3JlZ2lhb19ncmFmaWNvIDwtIGdncGxvdChwcmV2YWxlbmNpYV9yZWdpYW8sIGFlcyh4PVJlZ2lhbywgeT1QcmV2YWxlbmNpYSkpICsgCiAgZ2VvbV9jb2woZmlsbD0icGFsZWdyZWVuIiwgd2lkdGggPSAwLjUsIGFlcyh0ZXh0ID0gcGFzdGUoJ0FSUzogJywgUmVnaWFvLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnPGJyPlRheGEgZGUgSW5jaWTDqm5jaWEgQ3VtdWxhdGl2YSAoJSk6ICcsIFByZXZhbGVuY2lhKSkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgbGFicyh5PSJQcmV2YWzDqm5jaWEgKCUpIiwgeD0iIikgKwogIHRoZW1lKGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpKQoKcHJldmFsZW5jaWFfcmVnaWFvX2dyYWZpY29faW50ZXJhdGl2byA8LSBnZ3Bsb3RseShwcmV2YWxlbmNpYV9yZWdpYW9fZ3JhZmljbywgdG9vbHRpcCA9ICJ0ZXh0IikgJT4lIAogIGxheW91dCh5YXhpcyA9IGxpc3QodGl0bGUgPSBwYXN0ZTAoYyhyZXAoIiZuYnNwOyIsIDIwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRheGEgZGUgSW5jaWTDqm5jaWEgQ3VtdWxhdGl2YSAoJSkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXAoIiZuYnNwOyIsIDIwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCJcbiZuYnNwOyIsIDIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlID0gIiIpKSkKI01hcGEKcHJldmFsZW5jaWFfcmVnaWFvX29yZGVtIDwtIHByZXZhbGVuY2lhX3JlZ2lhb1tjKDQsNSw2LDIsNywxLDMpLF0gIyBjb2xvY2FyIGFzIHJlZ2lvZXMgcGVsYSBvcmRlbSBkbyBtYXBhCnByZXZhbGVuY2lhX3JlZ2lhb19vcmRlbVssMV0gPC0gYygiQWxlbnRlam8iLCAiQWxnYXJ2ZSIsICJBw6dvcmVzIiwgIkNlbnRybyIsICJNYWRlaXJhIiwgIk5vcnRlIiwgIkxpc2JvYSBlIFZhbGUgZG8gVGVqbyIgKQoKcGFsX3ByZXZhbGVuY2lhX3JlZ2lhbyA8LSBjb2xvckJpbigidmlyaWRpcyIsIGRvbWFpbiA9IHByZXZhbGVuY2lhX3JlZ2lhb19vcmRlbSRQcmV2YWxlbmNpYSwgYmlucyA9IGMoMC4xLCAwLjMsIDAuNSwgMC44LCAxLCAxLjMsIDEuNSwgSW5mKSkKCmxhYmVsc19wcmV2YWxlbmNpYV9yZWdpYW8gPC0gcGFzdGUoIAogICI8c3Ryb25nPiIsIHByZXZhbGVuY2lhX3JlZ2lhb19vcmRlbVssMV0sIjwvc3Ryb25nPjxici8+IiwgCiAgcm91bmQocHJldmFsZW5jaWFfcmVnaWFvX29yZGVtWywyXSwgZGlnaXRzID0gNCksICImIzM3PGJyLz4iLCAKICBzZXA9IiIpICU+JQogIGxhcHBseShodG1sdG9vbHM6OkhUTUwpCgpwcmV2YWxlbmNpYV9yZWdpYW9fbWFwYSA8LSBsZWFmbGV0KG1hcGFfcHQpICU+JQogIGFkZFBvbHlnb25zKHN0cm9rZSA9IFRSVUUsIAogICAgICAgICAgICAgIHNtb290aEZhY3RvciA9IDAuMywgCiAgICAgICAgICAgICAgZmlsbE9wYWNpdHkgPSAxLCAKICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsIAogICAgICAgICAgICAgIHdlaWdodCA9IDEsCiAgICAgICAgICAgICAgZmlsbENvbG9yID0gfnBhbF9wcmV2YWxlbmNpYV9yZWdpYW8ocHJldmFsZW5jaWFfcmVnaWFvX29yZGVtJFByZXZhbGVuY2lhKSwKICAgICAgICAgICAgICBsYWJlbCA9IGxhYmVsc19wcmV2YWxlbmNpYV9yZWdpYW8sIAogICAgICAgICAgICAgIGxhYmVsT3B0aW9ucyA9IGxhYmVsT3B0aW9ucyhzdHlsZSA9IGxpc3QoImZvbnQtd2VpZ2h0IiA9ICJub3JtYWwiLCBwYWRkaW5nID0gIjNweCA4cHgiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHRzaXplID0gIjEzcHgiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlyZWN0aW9uID0gImF1dG8iKSkgJT4lIAogIGFkZExlZ2VuZCgiYm90dG9tbGVmdCIsIAogICAgICAgICAgICBwYWwgPSBwYWxfcHJldmFsZW5jaWFfcmVnaWFvLCAKICAgICAgICAgICAgdmFsdWVzID0gcHJldmFsZW5jaWFfcmVnaWFvX29yZGVtJFByZXZhbGVuY2lhICwgCiAgICAgICAgICAgIG9wYWNpdHkgPSAwLjUsIAogICAgICAgICAgICB0aXRsZSA9ICJUYXhhIGRlIEluY2lkw6puY2lhIEN1bXVsYXRpdmEgKCUpIHBvciBBUlMiKSAlPiUgCiAgYWRkVGlsZXMoZ3JvdXAgPSJPcmlnaW5hbCIpICU+JQogIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJENhcnRvREIuUG9zaXRyb24sIGdyb3VwID0gIlBvc2l0cm9uIikgJT4lCiAgYWRkUHJvdmlkZXJUaWxlcyhwcm92aWRlcnMkRXNyaS5Xb3JsZEltYWdlcnksIGdyb3VwID0gIlNhdMOpbGl0ZSIpICU+JQogIGFkZExheWVyc0NvbnRyb2woYmFzZUdyb3VwcyA9IGMoIk9yaWdpbmFsIiwgIlBvc2l0cm9uIiwgIlNhdMOpbGl0ZSIpLCBvcHRpb25zID0gbGF5ZXJzQ29udHJvbE9wdGlvbnMoY29sbGFwc2VkID0gRkFMU0UpKQoKYnJvd3NhYmxlKAogIHRhZ0xpc3QobGlzdCgKICAgIHRhZ3MkZGl2KAogICAgICBzdHlsZSA9ICd3aWR0aDo1MCU7ZGlzcGxheTpibG9jaztmbG9hdDpsZWZ0OycsCiAgICAgIHByZXZhbGVuY2lhX3JlZ2lhb19tYXBhCiAgICApLAogICAgdGFncyRkaXYoCiAgICAgIHN0eWxlID0gJ3dpZHRoOjUwJTtkaXNwbGF5OmJsb2NrO2Zsb2F0OmxlZnQ7JywKICAgICAgcHJldmFsZW5jaWFfcmVnaWFvX2dyYWZpY29faW50ZXJhdGl2bwogICAgKQogICkpCikKYGBgCgojIyMgRmFpeGEgRXTDoXJpYSBlIEfDqW5lcm8gey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtZHJvcGRvd259CiMjIyMgTsO6bWVybyBkZSBDYXNvcyBwb3IgRmFpeGEgRXTDoXJpYSBlIHBvciBHw6luZXJvCgo8YnI+CgpOZXN0ZSBncsOhZmljbyBwb2RlbW9zIHZlciBxdWUgYSBtYWlvciBwYXJ0ZSBkb3MgY2Fzb3MgZXhpc3RlbnRlcyBzw6NvIGRhcyBmYWl4YXMgZXTDoXJpYXMgZW50cmUgb3MgMjAgZSBvcyA1OSBhbm9zLiBFc3RlIHZhbG9yIHBhcmVjZSBmYXplciBzZW50aWRvIHVtYSB2ZXogcXVlIGNvcnJlc3BvbmRlIMOgIHBvcHVsYcOnw6NvIGF0aXZhLCBnZXJhbG1lbnRlIGEgcG9wdWxhw6fDo28gbWFpcyBleHBvc3RhLiBObyBlbnRhbnRvLCDDqSBpbXBvcnRhbnRlIHJlYWzDp2FyIHF1ZSwgcG9yIHNlciB1bSB2YWxvciBhYnNvbHV0bywgbsOjbyB0w6ptIGVtIGNvbnNpZGVyYcOnw6NvIGEgcG9wdWxhw6fDo28gZGUgY2FkYSBmYWl4YSBldMOhcmlhLCBvIHF1ZSBzaWduaWZpY2EgcXVlIHBvZGUgaGF2ZXIgbWFpcyBjYXNvcyBuZXN0YXMgaWRhZGVzIHBvciBzZXJlbSBzaW11bHRhbmVhbWVudGUgYXMgZmFpeGFzIGV0w6FyaWFzIGNvbSBtYWlvciBuw7ptZXJvIGRlIHBlc3NvYXMgZW0gUG9ydHVnYWwuIAoKUG9yIG91dHJvIGxhZG8sIMOpIHZpc8OtdmVsIHF1ZSwgZW0gdG9kYXMgYXMgZmFpeGFzIGV0w6FyaWFzLCBvIGfDqW5lcm8gZmVtaW5pbm8gw6kgbyBxdWUgdGVtIG1haW9yIG7Dum1lcm8gZGUgY2Fzb3MsIGNvbSBleGNlw6fDo28gZG8gZ3J1cG8gZXTDoXJpbyBkb3MgMCBhb3MgOSBhbm9zLiBFc3RhIGFzc2ltZXRyaWEgcG9kZSBzZXIgZXhwbGljYWRhIHBvciwgZW0gbXVpdGFzIGRhcyBwcm9maXNzw7VlcyBjb20gZ3JhbmRlIGV4cG9zacOnw6NvIGFvIHbDrXJ1cywgYSBtYWlvcmlhIGRvcyB0cmFiYWxoYWRhcmVzIHPDo28gbXVsaGVyZXMuIE5vdmFtZW50ZSwgZXN0ZXMgZGFkb3MgcG9kZW0gbsOjbyBzZXIgZXN0YXRpc3RpY2FtZW50ZSBmacOhdmVpcyBwb3IgbsOjbyBzZSB0ZXIgdGlkbyBlbSBjb250YSBhIHBvcHVsYcOnw6NvIGV4aXN0ZW50ZSBkZSBjYWRhIGfDqW5lcm8uCgpgYGB7ciwgd2FybmluZz1GQUxTRX0KI1NlbGVjaW9uYXIgYXMgY29sdW5hcyBkZSBjb25maXJtYWRvcyBmZW1pbmlubyBwYXJhIHRvZGFzIGFzIGlkYWRlcyBlIGp1bnTDoS1sYXMgbnVtYSB0YWJlbGEgZSBmYXplciBvIG1lc21vIHBhcmEgbyBtYXNjdWxpbm8KZmVtaW5pbm9zIDwtIGFzLmRhdGEuZnJhbWUoY292aWQxOXB0ICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcGx5cjo6c2VsZWN0KHN0YXJ0c193aXRoKCJjb25maXJtYWRvc18iKSAmIChlbmRzX3dpdGgoIjlfZiIpfCBlbmRzX3dpdGgoInBsdXNfZiIpKSkpCm1hc2N1bGlub3MgPC0gYXMuZGF0YS5mcmFtZShjb3ZpZDE5cHQgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcGx5cjo6c2VsZWN0KChzdGFydHNfd2l0aCgiY29uZmlybWFkb3NfIikgJiAoZW5kc193aXRoKCI5X20iKXwgZW5kc193aXRoKCJwbHVzX20iKSkpKSkKCiNTZWxlY2lvbmFyIG8gdmFsb3IgbWFpcyByZWNlbnRlIGRlIGNhZGEgY29sdW5hIGRlIG1vZG8gYSBmaWNhciBjb20gbyBuw7ptZXJvIGRlIGNhc29zIGF0w6kgYW8gbW9tZW50byBwYXJhIGNhZGEgZmFpeGEgZXTDoXJpYSBlIHBhcmEgY2FkYSBnw6luZXJvCmNhc29zX2ZlbWluaW5vc19pZGFkZSA8LSBhcy5kYXRhLmZyYW1lKGxhcHBseShmZW1pbmlub3MsIGxhc3QpKQpjYXNvc19tYXNjdWxpbm9zX2lkYWRlIDwtIGFzLmRhdGEuZnJhbWUobGFwcGx5KG1hc2N1bGlub3MsIGxhc3QpKQoKI0NyaWFyIHRhYmVsYSBjb20gdW1hIGNvbHVuZGEgcGFyYSBhIGZhaXhhIGV0w6FyaWEgZSBvdXRyYSBwYXJhIG8gbsO6bWVybyBkZSBjYXNvcyBmZW1pbmlub3MgZSBtdWRhciBjb2x1bmEgZGEgZmFpeGEgZXTDoXJpYSBwYXJhIG9zIG5vbWVzIGFkZXF1YWRvcwpjYXNvc19mZW1pbmlub3NfaWRhZGVfaW52ZXJ0aWRvIDwtIGFzLmRhdGEuZnJhbWUodChjYXNvc19mZW1pbmlub3NfaWRhZGUpKSAlPiUgCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJJZGFkZSIpCm5hbWVzKGNhc29zX2ZlbWluaW5vc19pZGFkZV9pbnZlcnRpZG8pWzJdIDwtICJGZW1pbmlubyIKY2Fzb3NfZmVtaW5pbm9zX2lkYWRlX2ludmVydGlkb1ssMV0gPC0gYygiMC05IiwgIjEwLTE5IiwgIjIwLTI5IiwgIjMwLTM5IiwgIjQwLTQ5IiwgIjUwLTU5IiwgIjYwLTY5IiwgIjcwLTc5IiwgIjgwKyIpCgojQ3JpYXIgdGFiZWxhIGNvbSB1bWEgY29sdW5kYSBwYXJhIGEgZmFpeGEgZXTDoXJpYSBlIG91dHJhIHBhcmEgbyBuw7ptZXJvIGRlIGNhc29zIG1hc2N1bGlub3MgZSBtdWRhciBjb2x1bmEgZGEgZmFpeGEgZXTDoXJpYSBwYXJhIG9zIG5vbWVzIGFkZXF1YWRvcwpjYXNvc19tYXNjdWxpbm9zX2lkYWRlX2ludmVydGlkbyA8LSBhcy5kYXRhLmZyYW1lKHQoY2Fzb3NfbWFzY3VsaW5vc19pZGFkZSkpICU+JSAKICByb3duYW1lc190b19jb2x1bW4odmFyID0gIklkYWRlIikKbmFtZXMoY2Fzb3NfbWFzY3VsaW5vc19pZGFkZV9pbnZlcnRpZG8pWzJdIDwtICJNYXNjdWxpbm8iCmNhc29zX21hc2N1bGlub3NfaWRhZGVfaW52ZXJ0aWRvWywxXSA8LSBjKCIwLTkiLCAiMTAtMTkiLCAiMjAtMjkiLCAiMzAtMzkiLCAiNDAtNDkiLCAiNTAtNTkiLCAiNjAtNjkiLCAiNzAtNzkiLCAiODArIikKCiNKdW50YXIgYXMgMyB0YWJlbGFzIHF1ZSBjcmnDoW1vcwpjYXNvc19mZW1fbWFzYyA8LSBtZXJnZShjYXNvc19mZW1pbmlub3NfaWRhZGVfaW52ZXJ0aWRvLCBjYXNvc19tYXNjdWxpbm9zX2lkYWRlX2ludmVydGlkbywgYnkgPSAiSWRhZGUiKQoKI0ZhemVyIG1lbHQgcGFyYSBwb2RlciBmYXplciBncsOhZmljbyAKY2Fzb3NfZmVtX21hc2NfbWVsdCA8LSBtZWx0KGNhc29zX2ZlbV9tYXNjLCBpZC52YXJzID0gIklkYWRlIikKbmFtZXMoY2Fzb3NfZmVtX21hc2NfbWVsdCkgPSBjKCJJZGFkZSIsICJHZW5lcm8iLCAiQ2Fzb3MiKQoKIyMjRmF6ZXIgZ3LDoWZpY28gZGUgYmFycmFzIGNvbSBpZGFkZSBubyBlaXhvIGRvIHgsIG8gbsO6bWVybyBkZSBjYXNvcyBubyBlaXhvIGRvIHkgZSBvIGfDqW5lcm8gZW0gY2FkYSBiYXJyYQpjYXNvc19mZW1fbWFzY19ncmFmaWNvIDwtIGdncGxvdChjYXNvc19mZW1fbWFzY19tZWx0LCBhZXMoeCA9IElkYWRlLCB5ID0gQ2Fzb3MsIGZpbGwgPSBHZW5lcm8pKSArCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiLCBhZXModGV4dCA9IHBhc3RlKCdGYWl4YSBFdMOhcmlhOiAnLCBJZGFkZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJzxicj5Hw6luZXJvOiAnLCBHZW5lcm8sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+TsK6IGRlIENhc29zOiAnLCBDYXNvcykpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsKICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoMCwgbWF4KGNhc29zX2ZlbV9tYXNjX21lbHQkQ2Fzb3MgKyAxMDAwKSkpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIGxhYnMoeCA9ICIiLAogICAgICAgeSA9ICJNb3J0ZXMiKSArCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dCggc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTgsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIpKSArCiAgZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKHRpdGxlPSJHw6luZXJvIikpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJkZWVwcGluazMiLCAibGlnaHRibHVlIiwgImdyZXk2MCIpKQoKI0ZhemVyIGdyw6FmaWNvIGludGVyYXRpdm8KZ2dwbG90bHkoY2Fzb3NfZmVtX21hc2NfZ3JhZmljbywgdG9vbHRpcCA9ICJ0ZXh0IikgJT4lIAogIGxheW91dCh5YXhpcyA9IGxpc3QodGl0bGUgPSBwYXN0ZTAoYyhyZXAoIiZuYnNwOyIsIDIwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk7Dum1lcm8gZGUgQ2Fzb3MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXAoIiZuYnNwOyIsIDIwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCJcbiZuYnNwOyIsIDIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlID0gIiIpKSwKICAgICAgICAgbGVnZW5kID0gbGlzdCh4ID0gMSwgeSA9IDApKQpgYGAKCgojIyMjIEV2b2x1w6fDo28gZGEgSW5jaWTDqm5jaWEgcG9yIEZhaXhhIEV0w6FyaWEKCjxicj4KCk5lc3RlIGdyw6FmaWNvIGRlIMOhcmVhIHBvZGVtb3MgdmVyaWZpY2FyIHF1ZSBhcyBmYWl4YXMgZXTDoXJpYXMgZW50cmUgb3MgMCBlIG9zIDE5IGFub3MsIGFwcmVzZW50YXJhbSBpbmljaWFsbWVudGUgdW0gYmFpeG8gbsO6bWVybyBkZSBub3ZvcyBjYXNvcyBkacOhcmlvcy4gTm9zIG1lc2VzIGRlIHZlcsOjbyB2ZXJpZmljb3Utc2UgdW0gYXVtZW50byBkbyBuw7ptZXJvIGRlIGNhc29zLCBxdWUgc2UgdG9ybm91IG1haXMgZXhwcmVzc2l2byBhIHBhcnRpciBkZSBzZXRlbWJybywgbyBxdWUgcG9kZXLDoSBzZXIgZXhwbGljYWRvIHBlbG8gcmVncmVzc28gZG9zIGVzdHVkYW50ZXMgw6BzIGF1bGFzIGUgcGVsbyByZWdyZXNzbyBkb3MgcGFpcyBhb3MgZW1wcmVnb3MuCgpSZWxhdGl2YW1lbnRlIMOgcyBmYWl4YXMgZXTDoXJpYXMgZW50cmUgb3MgMjAgZSBvcyA1OSBhbm9zLCBlc3RhcyBhcHJlc2VudGFyYW0gdW0gY29tcG9ydGFtZW50byBzZW1lbGhhbnRlLCB1bWEgdmV6IHF1ZSBjb3JyZXNwb25kZW0gw6AgcG9wdWxhw6fDo28gYXRpdmEsIG1hbnRlbmRvLXNlIG8gbsO6bWVybyBkZSBub3ZvcyBjYXNvcyBkacOhcmlvcyBlbSB0b3JubyBkb3MgbWVzbW9zIHZhbG9yZXMuCgpOYXMgZmFpeGFzIGV0w6FyaWFzIGEgcGFydGlyIGRvcyA2MCBhbm9zLCDDqSBwb3Nzw612ZWwgdmVyaWZpY2FyIHF1ZSBubyBtw6pzIGRlIGFicmlsIGhvdXZlIHVtIG1haW9yIG7Dum1lcm8gZGUgbm92b3MgY2Fzb3MgZGnDoXJpb3MsIG8gcXVlIGNvaW5jaWRpdSBjb20gb3Mgc3VydG9zIGluaWNpYWlzIGRhIGRvZW7Dp2EsIG5vbWVhZGFtZW50ZSBub3MgbGFyZXMuIERlIHNlZ3VpZGEsIGhvdXZlIHVtYSBkaW1pbnVpw6fDo28gZGEgaW5jaWTDqm5jaWEgcHJvdmF2ZWxtZW50ZSBkZXZpZG8gYSB1bWEgY3Jlc2NlbnRlIHByZW9jdXBhw6fDo28gcGVsYSBwcm90ZcOnw6NvIGRvcyBncnVwb3MgZXTDoXJpb3MgZGUgcmlzY28uIEEgcGFydGlyIGRlIHNldGVtYnJvLCDDqSBkZSBub3RhciB1bSBub3ZvIGNyZXNjaW1lbnRvIG5vIG7Dum1lcm8gZGUgY2Fzb3MgZGnDoXJpb3MsIHBvZGVuZG8gaXN0byBzZXIganVzdGlmaWNhZG8gcG9yIHVtIG1haW9yIGNvbnRhY3RvIGNvbSBmYWl4YXMgZXTDoXJpYXMgbWFpcyBhdGl2YXMgKGZpbGhvcyBlIG5ldG9zKS4gCgpgYGB7ciwgd2FybmluZz1GQUxTRX0KI1BlZ2FuZG8gbmFzIHRhYmVsYXMgcXVlIGZpesOpbW9zIHBvciBnw6luZXJvIG9yIGZhaXhhIGV0w6FyaWEsIGNvbW8gb3MgdmFsb3JlcyBuYSBiYXNlIGRlIGRhZG9zIHPDo28gY3VtdWxhdGl2b3MsIGZhemVtb3MgbyB2YWxvciBkZXNzZSBkaWEgbWVub3MgbyB2YWxvciBkbyBkaWEgYW50ZXJpb3IgcGFyYSBvYnRlcm1vcyBvIG7Dum1lcm8gZGUgbm92b3MgY2Fzb3MgcG9yIGRpYSwgcG9yIGZhaXhhIGV0w6FyaWEgcG9yIGfDqW5lcm8KZmVtaW5pbm9zX25vdm9zIDwtIGZlbWluaW5vcyAtIGxhZyhmZW1pbmlub3MpCm1hc2N1bGlub3Nfbm92b3MgPC0gbWFzY3VsaW5vcyAtIGxhZyhtYXNjdWxpbm9zKQoKI0NyaWFyIHVtYSB0YWJlbGEgY29tIHVtYSBjb2x1bmEgcGFyYSBhIGRhdGEgZSBvdXRyYXMgY29sdW5hcyBjb20gbyBuw7ptZXJvIGRlIGNhc29zIHBvciBkaWEgcG9yIGZhaXhhIGV0w6FyaWEgYXBlbmFzIHF1ZSByZXN1bHRhbSBkYSBzb21hIGRvcyBub3ZvcyBjYXNvcyBmZW1pbmlub3MgY29tIG9zIG5vdm9zIGNhc29zIG1hc2N1bGlub3MKY2Fzb3NfdG90YWxfdGVtcG8gPC0gY2JpbmQoY292aWQxOXB0JGRhdGEsIGFzLmRhdGEuZnJhbWUoZmVtaW5pbm9zX25vdm9zICsgbWFzY3VsaW5vc19ub3ZvcykpCgojQ29tbyAgbGluaGEgNyBxdWUgw6kgYSBwcmltZWlyYSBlbSBxdWUgaMOhIHJlZ2lzdG8gZG9zIGNhc29zIGrDoSByZXByZXNlbnRhIG8gbsO6bWVybyBkZSBjYXNvcyBuZXNzZSBkaWEgYXBlbmFzLCBhZGljaW9uw6Ftb3MgZXNzYSBsaW5oYSDDoCB0YWJlbGEgZSBkYXIgbm9tZXMgw6BzIGNvbHVuYXMKY2Fzb3NfdG90YWxfdGVtcG9bNywgMjoxMF0gPC0gZmVtaW5pbm9zWzcsXSArIG1hc2N1bGlub3NbNyxdCm5hbWVzKGNhc29zX3RvdGFsX3RlbXBvKTwtIGMoIkRhdGEiLCAiMC05IiwgIjEwLTE5IiwgIjIwLTI5IiwgIjMwLTM5IiwgIjQwLTQ5IiwgIjUwLTU5IiwgIjYwLTY5IiwgIjcwLTc5IiwgIjgwKyIpCgojRmF6ZXIgbWVsdCBwYXJhIGZhemVyIG8gZ3LDoWZpY28KY2Fzb3NfdG90YWxfdGVtcG9fbWVsdCA8LSBtZWx0KGNhc29zX3RvdGFsX3RlbXBvLCBpZC52YXJzID0gIkRhdGEiKQpuYW1lcyhjYXNvc190b3RhbF90ZW1wb19tZWx0KSA9IGMoIkRhdGEiLCAiRmFpeGFfRXRhcmlhIiwgIkNhc29zIikKCiNGYXplciBvIGdyw6FmaWNvIGRlIMOhcmVhIGNvbSBhIGRhdGEgbm8gZWl4byBkbyB4LCBvIG7Dum1lcm8gZGUgY2Fzb3Mgbm8gZWl4byBkbyB5IGUgYSBmYWl4YSBldMOhcmlhIGVtIGNhZGEgbGluaGEKY2Fzb3NfdG90YWxfdGVtcG9fZ3JhZmljbyA8LSBnZ3Bsb3QoY2Fzb3NfdG90YWxfdGVtcG9fbWVsdCwgYWVzKHggPSBEYXRhLCB5ID0gQ2Fzb3MsIGZpbGwgPSBGYWl4YV9FdGFyaWEpKSArCiAgZ2VvbV9hcmVhKGFscGhhPTAuNiAsIHNpemU9LjUpICsKICBsYWJzKHggPSIiLCAKICAgICAgIHkgPSAiSW5jaWTDqm5jaWEiKSArCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA1KSwKICAgICAgICBzdHJpcC50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDMsIGFuZ2xlID0gMCkpICsKICBzY2FsZV94X2RhdGUoYnJlYWtzID0gIm1vbnRocyIsIGRhdGVfbGFiZWxzID0gIiViIikKCiNUb3JuYXIgZ3LDoWZpY28gaW50ZXJhdGl2bwpjYXNvc190b3RhbF90ZW1wb19ncmFmaWNvX2ludGVyYXRpdm8gPC0gZ2dwbG90bHkoY2Fzb3NfdG90YWxfdGVtcG9fZ3JhZmljbykgJT4lIAogIGxheW91dChsZWdlbmQgPSBsaXN0KHggPSAxLCB5ID0gMCkpCgojTsO6bWVybyBkZSBjYXNvcyBjb20gbcOpZGlhIHJvbGFudGUKIyNDYWxjdWxhciBhIG3DqWRpYSByb2xhbnRlCmNhc29zX3RvdGFsX3RlbXBvX21lZGlhX3JvbGFudGUgPC0gY2JpbmQoY2Fzb3NfdG90YWxfdGVtcG9bNzpucm93KGNhc29zX3RvdGFsX3RlbXBvKSwxXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXMuZGF0YS5mcmFtZShyb2xsbWVhbihjYXNvc190b3RhbF90ZW1wb1ssMjoxMF0sayA9IDcpKSkKbmFtZXMoY2Fzb3NfdG90YWxfdGVtcG9fbWVkaWFfcm9sYW50ZSlbMV0gPSAiRGF0YSIKCiMjRmF6ZXIgbWVsdApjYXNvc190b3RhbF90ZW1wb19tZWRpYV9yb2xhbnRlX21lbHQgPC0gbWVsdChjYXNvc190b3RhbF90ZW1wb19tZWRpYV9yb2xhbnRlLCBpZC52YXJzID0gIkRhdGEiKQpuYW1lcyhjYXNvc190b3RhbF90ZW1wb19tZWRpYV9yb2xhbnRlX21lbHQpID0gYygiRGF0YSIsICJGYWl4YV9FdGFyaWEiLCAiQ2Fzb3MiKQoKIyNGYXplciBncsOhZmljbyBkZSBsaW5oYXMKY2Fzb3NfdG90YWxfdGVtcG9fbWVkaWFfcm9sYW50ZV9ncmFmaWNvX2xpbmhhcyA8LSBnZ3Bsb3QoY2Fzb3NfdG90YWxfdGVtcG9fbWVkaWFfcm9sYW50ZV9tZWx0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBEYXRhLCB5ID0gQ2Fzb3MsIGNvbG9yID0gRmFpeGFfRXRhcmlhKSkgKwogIGdlb21fcG9pbnQoc2l6ZT0wLjEsIGFlcyh0ZXh0ID0gcGFzdGUoJ0RhdGE6ICcsIERhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+RmFpeGEgRXTDoXJpYTogJywgRmFpeGFfRXRhcmlhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnPGJyPkluY2lkw6puY2lhOiAnLCBDYXNvcykpKSArCiAgZ2VvbV9saW5lKHNpemU9MC41KSArCiAgbGFicyh0aXRsZSA9ICJNw6lkaWEgUm9sYW50ZSAoNyBkaWFzKSIsCiAgICAgICB4ID0iIiwgCiAgICAgICB5ID0gIkluY2lkw6puY2lhIikgKwogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksCiAgICAgICAgc3RyaXAudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAzLCBhbmdsZSA9IDApKSArCiAgc2NhbGVfeF9kYXRlKGJyZWFrcyA9ICIzIG1vbnRocyIsIGRhdGVfbGFiZWxzID0gIiViICVkIikKCiMjVG9ybmFyIGdyw6FmaWNvIGludGVyYXRpdm8KY2Fzb3NfdG90YWxfdGVtcG9fbWVkaWFfcm9sYW50ZV9ncmFmaWNvX2xpbmhhc19pbnRlcmF0aXZvIDwtIGdncGxvdGx5KGNhc29zX3RvdGFsX3RlbXBvX21lZGlhX3JvbGFudGVfZ3JhZmljb19saW5oYXMsIHRvb2x0aXAgPSAidGV4dCIpCiAKCgpicm93c2FibGUoCiAgdGFnTGlzdChsaXN0KAogICAgdGFncyRkaXYoCiAgICAgIHN0eWxlID0gJ3dpZHRoOjUwJTtkaXNwbGF5OmJsb2NrO2Zsb2F0OmxlZnQ7JywKICAgICAgY2Fzb3NfdG90YWxfdGVtcG9fZ3JhZmljb19pbnRlcmF0aXZvCiAgICApLAogICAgdGFncyRkaXYoCiAgICAgIHN0eWxlID0gJ3dpZHRoOjUwJTtkaXNwbGF5OmJsb2NrO2Zsb2F0OmxlZnQ7JywKICAgICAgY2Fzb3NfdG90YWxfdGVtcG9fbWVkaWFfcm9sYW50ZV9ncmFmaWNvX2xpbmhhc19pbnRlcmF0aXZvCiAgICApCiAgKSkKKQpgYGAKCgojIyMjIEV2b2x1w6fDo28gVGF4YSBkZSBJbmNpZMOqbmNpYSBwb3IgRmFpeGEgRXTDoXJpYQo8YnI+CgpOb3ZhbWVudGUgbmVzdGUgZ3LDoWZpY28sIMOpIHBvc3PDrXZlbCBvYnNlcnZhciBxdWUgYXMgZmFpeGFzIGV0w6FyaWFzIGRvcyAwIGFvcyAxOSBhbm9zIGFwcmVzZW50YXJhbSB1bWEgYmFpeGEgdGF4YSBkZSBpbmNpZMOqbmNpYSwgbWVzbW8gbm9zIHByaW1laXJvcyBtZXNlcyBkYSBwYW5kZW1pYSwgdGVuZG8tc2UgbWFudGlkbyByZWxhdGl2YW1lbnRlIGVzdMOhdmVsLiBEZXNkZSBzZXRlbWJybywgZXN0ZXMgdmFsb3JlcyB0w6ptIGF1bWVudGFkbyBuYSBzZXF1w6puY2lhIGRvIGluw61jaW8gZG8gcGVyw61vZG8gZXNjb2xhci4KCk5vIGNhc28gZGFzIGZhaXhhcyBldMOhcmlhcyBlbnRyZSBvcyAyMCBlIG9zIDM5IGFub3MsIGluaWNpYWxtZW50ZSBhcHJlc2VudGFyYW0gdmFsb3JlcyBkZSB0YXhhIGRlIGluY2lkw6puY2lhIG1haXMgZWxldmFkb3MsIGRpbWludWluZG8gcG9zdGVyaW9ybWVudGUgbWFzIHNlbXByZSBjb20gYWxndW1hIGluc3RhYmlsaWRhZGUsIG7Do28gc8OzIHBvciBwZXJ0ZW5jZXJlbSBhIHVtYSBmcmHDp8OjbyBhdGl2YSBkYSBwb3B1bGHDp8OjbywgbWFzIHRhbWLDqW0gcGVsYSBtYWlvciB0ZW5kw6puY2lhIHBhcmEgZnJlcXVlbnRhciBsb2NhaXMgY29tIG1haW9yZXMgYWdsb21lcmFkb3MgZGUgaW5kaXbDrWR1b3MuIERvcyA0MCBhb3MgNTkgYW5vcyBvIGNvbXBvcnRhbWVudG8gZGEgY3VydmEgw6kgc2VtZWxoYW50ZSwgbm8gZW50YW50byBtYW50ZXZlLXNlIG1haXMgb3UgbWVub3MgY29uc3RhbnRlIGR1cmFudGUgb3MgbWVzZXMgZGUgVmVyw6NvLCB0ZW5kbyB2b2x0YWRvIGEgYXVtZW50YXIgYSBwYXJ0aXIgZGUgc2V0ZW1icm8sIG8gcXVlIG1pbWV0aXphIG8gY29tcG9ydGFtZW50byBkYXMgZmFpeGFzIGV0w6FyaWFzIGFudGVyaW9yZXMuCgpSZWxhdGl2YW1lbnRlIMOgcyBmYWl4YXMgZXTDoXJpYXMgZG9zIDYwIGFvcyA3OSBhbm9zLCBwb2RlbW9zIHZlcmlmaWNhciBxdWUgYSB0YXhhIGRlIGluY2lkw6puY2lhIGZvaSBwcmluY2lwYWxtZW50ZSBwcmVvY3VwYW50ZSBub3MgbWVzZXMgaW5pY2lhaXMgZGEgcGFuZGVtaWEsIHRlbmRvIGRlcG9pcyBlc3RhYmlsaXphZG8gYXTDqSBtZWFkb3MgZGUgc2V0ZW1icm8sIG5vdmFtZW50ZSByZXN1bHRhbnRlIGRlIHVtYSBjcmVzY2VudGUgcHJlb2N1cGHDp8OjbyBwZWxvIGdydXBvIGV0w6FyaW8gbWFpcyBzdXNjZXTDrXZlbC4gRGEgbWVzbWEgZm9ybWEsIGEgZmFpeGEgZXTDoXJpYSBkb3MgODArIGFwcmVzZW50b3UgdW1hIHRheGEgZGUgaW5jaWTDqm5jaWEgaW5pY2lhbCBhbGFybWFudGUsIG5vIGVudGFudG8gbnVuY2EgY29uc2VndWl1IGVzdGFiaWxpemFyIGRhIG1lc21hIGZvcm1hLCBwcm92YXZlbG1lbnRlIGRlY29ycmVudGUgZGUgZGl2ZXJzb3Mgc3VydG9zIGVtIGxhcmVzIGFvIGxvbmdvIGRvIHRlbXBvLgoKYGBge3IsIHdhcm5pbmc9RkFMU0V9CiNEYWRvcyBkYSBwb3B1bGHDp8OjbyBkZSBwb3J0dWdhbCBlbSA8aHR0cHM6Ly93d3cucG9yZGF0YS5wdC9Qb3J0dWdhbC9Qb3B1bGElQzMlQTclQzMlQTNvK3Jlc2lkZW50ZSsrbSVDMyVBOWRpYSthbnVhbCt0b3RhbCtlK3BvcitncnVwbytldCVDMyVBMXJpby0xMD4KcHRfMF85ID0gNDMzMzMyCSsgNDYxMjk5CnB0XzEwXzE5ID0gNTA3NjQ2ICsgNTQ5MDMzCnB0XzIwXzI5ID0gNTQ0NTc1ICsgNTQ3NTA1CnB0XzMwXzM5ID0gNTcxMzU1ICsgNjc5MDkzCnB0XzQwXzQ5ID0gNzkyNjcwICsgNzgyNTU1CnB0XzUwXzU5ID0gNzQ3NTgxICsgNzM0NTQwCnB0XzYwXzY5ID0gNjcyNzU4ICsgNjIwNTQzCnB0XzcwXzc5ID0gNTQ0MDE2ICsgNDI5MTA3CnB0XzgwX3BsdXMgPSAzNTIyMTggKyAzMTY0NDIKCiNGYXplciB0YWJlbGEgY29tIHBvcHVsYcOnw6NvIHBvciBmYWl4YSBldMOhcmlhCnBvcHVsYWNhb19pZGFkZXNfcHQgPC0gYXMuZGF0YS5mcmFtZShjKHB0XzBfOSwgcHRfMTBfMTksIHB0XzIwXzI5LCBwdF8zMF8zOSwgcHRfNDBfNDksIHB0XzUwXzU5LCBwdF82MF82OSwgcHRfNzBfNzksIHB0XzgwX3BsdXMpKQoKIyNSZXBldGlyIHZhbG9yZXMgZGEgcG9wdWxhw6fDo28gcG9yIGZhaXhhIGV0w6FyaWEgcGFyYSBmaWNhciBjb20gbWVzbW8gbsO6bWVybyBkZSBsaW5oYXMgZGEgYmFzZSBkZSBkYWRvcwpwb3B1bGFjYW9faWRhZGVzX3B0X3JlcCA8LSBhcy5kYXRhLmZyYW1lKHQocG9wdWxhY2FvX2lkYWRlc19wdFtyZXAoc2VxX2xlbihuY29sKHBvcHVsYWNhb19pZGFkZXNfcHQpKSwgZWFjaCA9IG5yb3coY292aWQxOXB0KSldKSkKCiNDYWxjdWxhciBhIHBvcHVsYcOnw6NvIGRlIHJpc2NvIHN1YnRyYWluZG8gw6AgcG9wdWxhw6fDo28gcG9yIGZhaXhhIGV0w6FyaWEgbyBuw7ptZXJvIGRlIMOzYml0b3MgZSBvIG7Dum1lcm8gZGUgY2Fzb3MgYXTDqSBhbyBtb21lbnRvICAgICAgICAgICAgICAgIApwb3B1bGFjYW9fcmlzY29faWRhZGUgPC0gcG9wdWxhY2FvX2lkYWRlc19wdF9yZXAgLSBmZW1pbmlub3MgLSBtYXNjdWxpbm9zCgojQ2FsY3VsYXIgYSB0YXhhIGRlIGluY2lkw6puY2lhLCByZXRpcmFuZG8gYSBjb2x1bmEgZGFzIGRhdGFzCnRheGFfaW5jaWRlbmNpYV9pZGFkZSA8LSAoY2Fzb3NfdG90YWxfdGVtcG9bLC0xXS9wb3B1bGFjYW9fcmlzY29faWRhZGUpKjEwMAoKI1ZvbHRhciBhIGFkaWNpb25hciBhIGNvbHVuYSBkYSBkYXRhIGUgZmF6ZXIgbWVsdCBwYXJhIGZhemVyIG8gZ3LDoWZpY28KdGF4YV9pbmNpZGVuY2lhX2lkYWRlIDwtIGNiaW5kKGNvdmlkMTlwdCRkYXRhLCB0YXhhX2luY2lkZW5jaWFfaWRhZGUpCm5hbWVzKHRheGFfaW5jaWRlbmNpYV9pZGFkZSlbMV0gPSAiRGF0YSIKdGF4YV9pbmNpZGVuY2lhX2lkYWRlX21lbHQgPC0gbWVsdCh0YXhhX2luY2lkZW5jaWFfaWRhZGUsIGlkLnZhcnMgPSAiRGF0YSIpCm5hbWVzKHRheGFfaW5jaWRlbmNpYV9pZGFkZV9tZWx0KSA9IGMoIkRhdGEiLCAiRmFpeGFfRXRhcmlhIiwgIlRheGFfSW5jaWRlbmNpYSIpCgojRmF6ZXIgZ3LDoWZpY28gZGUgbGluaGFzIGNvbSBkYXRhIG5vIGVpeG8gZG8geCwgdGF4YSBkZSBpbmNpZMOqbmNpYSBubyBlaXhvIGRvIHkgZSBmYWl4YSBldMOhcmlhIG5hcyBjb3JlcyBkYXMgbGluaGFzCmdncGxvdCh0YXhhX2luY2lkZW5jaWFfaWRhZGVfbWVsdCwgYWVzKHggPSBEYXRhLCB5ID0gVGF4YV9JbmNpZGVuY2lhLCBjb2xvciA9IEZhaXhhX0V0YXJpYSkpICsKICBnZW9tX2xpbmUoc2l6ZSA9IDAuOCkrCiAgZmFjZXRfZ3JpZCh0YXhhX2luY2lkZW5jaWFfaWRhZGVfbWVsdCRGYWl4YV9FdGFyaWEpKwogIGd1aWRlcyhjb2xvciA9IEZBTFNFKSArCiAgbGFicyh4ID0gIiIsCiAgICAgICB5ID0iVGF4YSBkZSBJbmNpZMOqbmNpYSAoJSkiKSArCiAgdGhlbWUoYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbihyID0gMjAsIGwgPSAyMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxMiksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLAogICAgICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCwgYW5nbGUgPSAwKSkgKwogIHNjYWxlX3hfZGF0ZShicmVha3MgPSAiMyBtb250aHMiLCBkYXRlX2xhYmVscyA9ICIlYiAlZCIpCmBgYAoKIyMjIyBUYXhhIGRlIEluY2lkw6puY2lhIEN1bXVsYXRpdmEgcG9yIEZhaXhhIEV0w6FyaWEKCjxicj4KCgpOZXN0ZSBncsOhZmljbyBkZSBiYXJyYXMgw6kgcG9zc8OtdmVsIHZlciBxdWUsIMOgIGRhdGEgZGVzdGEgYW7DoWxpc2UsIGEgZmFpeGEgZXTDoXJpYSBjb20gbWFpb3IgcHJldmFsw6puY2lhIMOpIGEgZG9zIDgwKyBhbm9zLiBJc3RvIHBvZGUgc2VyIGV4cGxpY2FkbyBwZWxvIGZhY3RvIGRlIGVzdGEgZmFpeGEgZXTDoXJpYSBuZWNlc3NpdGFyIGRlIG1haXMgY3VpZGFkb3MsIGVzdGFuZG8gcHJlc2VudGUgZW0gbGFyZXMgKG9uZGUgdMOqbSBvY29ycmlkbyBzdXJ0b3MpIG91IHJlY29ycmVuZG8gYSBjdWlkYWRvcmVzLCBzZW5kbyBwb3IgaXNzbyBtYWlzIHN1c2NldMOtdmVpcyDDoCBpbmZlw6fDo28uCgpBIGZhaXhhIGV0w6FyaWEgZG9zIDIwIGFvcyAyOSBhbm9zIMOpIGEgcXVlIGFwcmVzZW50YSBhIHNlZ3VuZGEgbWFpb3IgcHJldmFsw6puY2lhLCBzZW5kbyBub3TDs3JpbyBxdWUgZXN0ZSB2YWxvciB2YWkgZGltaW51aW5kbyDDoCBtZWRpZGEgcXVlIHNlIHByb2dyaWRlIG5hIGZhaXhhIGV0w6FyaWEsIGNvbSBleGNlw6fDo28gZGEgZmFpeGEgZXTDoXJpYSBkb3MgODArLCBwZWxvIGV4cGxpY2FkbyBhbnRlcmlvcm1lbnRlLiBJc3RvIHBvZGUgZGV2ZXItc2UgYW8gYXVtZW50byBkbyByZWNlaW8gZGEgZG9lbsOnYSBjb20gbyBhdW1lbnRvIGRhIGlkYWRlLgoKQXMgZmFpeGFzIGV0w6FyaWFzIGVudHJlIG9zIDkgZSBvcyAxOSBhbm9zIHPDo28gYXMgcXVlIHTDqm0gYXMgcHJldmFsw6puY2lhcyBtYWlzIGJhaXhhcywgbyBxdWUgcG9kZSBzZXIgZXhwbGljYWRvIHBlbG8gZW5jZXJyYW1lbnRvIGRhcyBlc2NvbGFzIHF1ZSBwcm9tb3ZldSB1bWEgbWFpb3IgcHJvdGXDp8OjbyBkYXMgY3JpYW7Dp2FzLiDDiSBhaW5kYSBwcmVtYXR1cm8gdGlyYXIgY29uY2x1c8O1ZXMgc29icmUgbyBpbXBhY3RvIHF1ZSBhIHJlYWJlcnR1cmEgZGFzIGVzY29sYXMgdGVyw6EgbmEgcHJldmFsw6puY2lhIGRlc3RhcyBmYWl4YXMgZXTDoXJpYXMuCgpSZWxhdGl2YW1lbnRlIMOgIGV2b2x1w6fDo28gZGEgcHJldmFsw6puY2lhIHBvciBmYWl4YSBldMOhcmlhLCBlbSBhYnJpbCDDqSB2aXPDrXZlbCBxdWUgYSBmYWl4YSBldMOhcmlhIGRvcyA4MCsgYW5vcyBlcmEgYSBxdWUgdGluaGEsIGRlIGxvbmdlLCBhIG1haW9yIHByZXZhbMOqbmNpYS4gw4kgZGUgbm90YXIgdGFiw6ltIHF1ZSBkZXNkZSBzZXRlbWJybyBxdWUgdG9kYXMgYXMgZmFpeGEgZXTDoXJpYXMgc29mcmVyYW0gdW0gbWFpb3IgYXVtZW50byBkYSBwcmV2YWzDqm5jaWEgY29tcGFyYWRvIGNvbSBvcyBtZXNlcyBhbnRlcmlvcmVzLgoKYGBge3IsIHdhcm5pbmc9RkFMU0V9CiMjI1NvbWFyIGEgdGFiZWxhIGRvcyBmZW1pbmlub3MgY29tIGEgZG9zIG1hc2N1bGlub3MgbyBxdWUgdmFpIGRhciBvIG7Dum1lcm8gZGUgY2Fzb3MgYXTDqSBhbyBtb21lbnRvIHBvciBpZGFkZSBhcGVuYXMKY2Fzb3NfdG90YWxfaWRhZGUgPC0gYXMuZGF0YS5mcmFtZShjYXNvc19mZW1pbmlub3NfaWRhZGUgKyBjYXNvc19tYXNjdWxpbm9zX2lkYWRlKQoKI0NhbGN1bGFyIHByZXZhbMOqbmNpYQpwcmV2YWxlbmNpYV9pZGFkZSA8LSAoKGFzLmRhdGEuZnJhbWUodChjYXNvc190b3RhbF9pZGFkZSkpKSoxMDAgLyBwb3B1bGFjYW9faWRhZGVzX3B0KSAlPiUgIAogIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAiRmFpeGFfRXRhcmlhIikKcHJldmFsZW5jaWFfaWRhZGVbLDFdID0gYygiMC05IiwgIjEwLTE5IiwgIjIwLTI5IiwgIjMwLTM5IiwgIjQwLTQ5IiwgIjUwLTU5IiwgIjYwLTY5IiwgIjcwLTc5IiwgIjgwKyIpCm5hbWVzKHByZXZhbGVuY2lhX2lkYWRlKVsyXSA9ICJQcmV2YWxlbmNpYSIKCiNGYXplciBncsOhZmljbyBjb20gZmFpeGEgZXTDoXJpYSBubyBlaXhvIGRvIHggZSBwcmV2YWzDqm5jaWEgbm8gZWl4byBkbyB5CnByZXZhbGVuY2lhX2lkYWRlX2dyYWZpY28gPC0gZ2dwbG90KHByZXZhbGVuY2lhX2lkYWRlLCBhZXMoeCA9IEZhaXhhX0V0YXJpYSwgeSA9IFByZXZhbGVuY2lhKSkgKwogIGdlb21fY29sKGZpbGwgPSAiY29yYWwyIiwgd2lkdGggPSAwLjUsIGFlcyh0ZXh0ID0gcGFzdGUoJ0ZhaXhhIGV0w6FyaWE6ICcsIEZhaXhhX0V0YXJpYSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+VGF4YSBkZSBJbmNpZMOqbmNpYSBDdW11bGF0aXZhICglKTonLCBQcmV2YWxlbmNpYSkpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIGxhYnMoeCA9ICIiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT04LCBjb2xvciA9ICJibGFjayIpLAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTIsIGNvbG9yID0gImJsYWNrIikpCgojVG9ybmFyIGdyw6FmaWNvIGludGVyYXRpdm8KcHJldmFsZW5jaWFfaWRhZGVfZ3JhZmljb19pbnRlcmF0aXZvIDwtIGdncGxvdGx5KHByZXZhbGVuY2lhX2lkYWRlX2dyYWZpY28sIHRvb2x0aXAgPSAidGV4dCIpICU+JSAKICBsYXlvdXQoeWF4aXMgPSBsaXN0KHRpdGxlID0gcGFzdGUwKGMocmVwKCImbmJzcDsiLCAyMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRheGEgZGUgSW5jaWTDqm5jaWEgQ3VtdWxhdGl2YSAoJSkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXAoIiZuYnNwOyIsIDIwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCJcbiZuYnNwOyIsIDIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlID0gIiIpKSkKI1ByZXZhbMOqbmNpYSBwb3IgZmFpeGEgZXTDoXJpYSBkacOhcmlhCgojI0PDoWxjdWxvIGRhIHByZXZhbMOqbmNpYQpwcmV2YWxlbmNpYV90ZW1wb19pZGFkZSA8LSBjYmluZChjb3ZpZDE5cHQkZGF0YSwgKChmZW1pbmlub3MgKyBtYXNjdWxpbm9zKSAvIHBvcHVsYWNhb19pZGFkZXNfcHRfcmVwKSoxMDApCm5hbWVzKHByZXZhbGVuY2lhX3RlbXBvX2lkYWRlKSA9IGMoIkRhdGEiLCAiMC05IiwgIjEwLTE5IiwgIjIwLTI5IiwgIjMwLTM5IiwgIjQwLTQ5IiwgIjUwLTU5IiwgIjYwLTY5IiwgIjcwLTc5IiwgIjgwKyIpCgojI0ZhemVyIG1lbHQgcGFyYSBmYXplciBvIGdyw6FmaWNvCnByZXZhbGVuY2lhX3RlbXBvX2lkYWRlX21lbHQgPC0gbWVsdChwcmV2YWxlbmNpYV90ZW1wb19pZGFkZSwgaWQudmFycyA9ICJEYXRhIikKbmFtZXMocHJldmFsZW5jaWFfdGVtcG9faWRhZGVfbWVsdCkgPSBjKCJEYXRhIiwgIkZhaXhhX0V0YXJpYSIsICJQcmV2YWxlbmNpYSIpCgojI0ZhemVyIGdyw6FmaWNvIGRlIGxpbmhhcyBjb20gZGF0YSBubyBlaXhvIGRvIHgsIHByZXZhbMOqbmNpYSBubyBlaXhvIGRvIHkgZSBmYWl4YSBldMOhcmlhIG5hcyBjb3JlcyBkYXMgbGluaGFzCnByZXZhbGVuY2lhX3RlbXBvX2lkYWRlX2dyYWZpY28gPC0gZ2dwbG90KHByZXZhbGVuY2lhX3RlbXBvX2lkYWRlX21lbHQsIGFlcyh4ID0gRGF0YSwgeSA9IFByZXZhbGVuY2lhLCBjb2xvciA9IEZhaXhhX0V0YXJpYSkpICsKICBnZW9tX2xpbmUoc2l6ZT0wLjUpKwogIGdlb21fcG9pbnQoc2l6ZT0wLjEsIGFlcyh0ZXh0ID0gcGFzdGUoICdEYXRhOiAnLCBEYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+RmFpeGEgRXTDoXJpYTogJywgRmFpeGFfRXRhcmlhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+VGF4YSBkZSBJbmNpZMOqbmNpYSBDdW11bGF0aXZhICglKTonLCBQcmV2YWxlbmNpYSkpKSArCiAgbGFicyh4ID0gIiIpICsKICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSA2KSkgKwogIHNjYWxlX3hfZGF0ZShicmVha3MgPSAiMyBtb250aHMiLCBkYXRlX2xhYmVscyA9ICIlYiAlZCIpCgojI1Rvcm5hciBvIGdyYWZpY28gaW50ZXJhdGl2bwpwcmV2YWxlbmNpYV90ZW1wb19pZGFkZV9ncmFmaWNvX2ludGVyYXRpdm8gPC0gZ2dwbG90bHkocHJldmFsZW5jaWFfdGVtcG9faWRhZGVfZ3JhZmljbywgdG9vbHRpcCA9ICJ0ZXh0IikgJT4lIAogIGxheW91dCh5YXhpcyA9IGxpc3QodGl0bGUgPSBwYXN0ZTAoYyhyZXAoIiZuYnNwOyIsIDIwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRheGEgZGUgSW5jaWTDqm5jaWEgQ3VtdWxhdGl2YSAoJSkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXAoIiZuYnNwOyIsIDIwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCJcbiZuYnNwOyIsIDEpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlID0gIiIpKSwKICAgICAgICAgbGVnZW5kID0gbGlzdCh4ID0gMSwgeSA9IDApKQoKYnJvd3NhYmxlKAogIHRhZ0xpc3QobGlzdCgKICAgIHRhZ3MkZGl2KAogICAgICBzdHlsZSA9ICd3aWR0aDo1MCU7ZGlzcGxheTpibG9jaztmbG9hdDpsZWZ0OycsCiAgICAgIHByZXZhbGVuY2lhX2lkYWRlX2dyYWZpY29faW50ZXJhdGl2bwogICAgKSwKICAgIHRhZ3MkZGl2KAogICAgICBzdHlsZSA9ICd3aWR0aDo1MCU7ZGlzcGxheTpibG9jaztmbG9hdDpsZWZ0OycsCiAgICAgIHByZXZhbGVuY2lhX3RlbXBvX2lkYWRlX2dyYWZpY29faW50ZXJhdGl2bwogICAgKQogICkpCikKYGBgCgojIyMjIEV2b2x1w6fDo28gZGEgSW5jaWTDqm5jaWEgcG9yIEfDqW5lcm8KPGJyPgoKQ29tbyBwb2RlbW9zIG9ic2VydmFyIGF0cmF2w6lzIGRlc3RlIGdyw6FmaWNvLCBhIGluY2lkw6puY2lhIGVtIGFtYm9zIG9zIGfDqW5lcm9zIGV2b2x1aXUgZGUgZm9ybWEgcmVsYXRpdmFtZW50ZSBzZW1lbGhhbnRlLCBzZW5kbyBxdWUgbyBnw6luZXJvIGZlbWluaW5vIGFwcmVzZW50b3UgdmFsb3JlcyBsaWdlaXJhbWVudGUgc3VwZXJpb3Jlcy4gw4kgcHJvdsOhdmVsIHF1ZSwgbm9zIG1lc2VzIGluaWNpYWlzIGRhIHBhbmRlbWlhLCBpbmRpdsOtZHVvcyBkbyBzZXhvIGZlbWluaW5vIHRlbmhhbSB0aWRvIG1haW9yIGNvbnRhY3RvIGRpcmV0byBjb20gZXN0YSBjb25kacOnw6NvIGNsw61uaWNhLCBldmVudHVhbG1lbnRlIHBlbGEgcHJvZmlzc8OjbyBxdWUgZXhlcmNlbS4KCk1haXMgdW1hIHZleiwgw6kgZGUgcmVmZXJpciBxdWUgZXN0YSBhbsOhbGlzZSBuw6NvIHRlbSBlbSBjb25zaWRlcmHDp8OjbyBvIG7Dum1lcm8gZGUgaW5kaXbDrWR1b3MsIHRhbnRvIGZlbWluaW5vcyBjb21vIG1hc2N1bGlub3MsIG5vIHRvdGFsIGRhIHBvcHVsYcOnw6NvLgoKYGBge3IsIHdhcm5pbmc9RkFMU0V9CiNEdWFzIHRhYmVsYXMgY29tIGNhc29zIGRpw6FyaW9zLCB1bWEgcGFyYSBjYWRhIGfDqW5lcm8KZmVtaW5pbm9zX3RvdGFsX25vdm9zIDwtIGFzLmRhdGEuZnJhbWUoY292aWQxOXB0JGNvbmZpcm1hZG9zX2YgLSBsYWcoY292aWQxOXB0JGNvbmZpcm1hZG9zX2YpKQptYXNjdWxpbm9zX3RvdGFsX25vdm9zIDwtIGFzLmRhdGEuZnJhbWUoY292aWQxOXB0JGNvbmZpcm1hZG9zX20gLSBsYWcoY292aWQxOXB0JGNvbmZpcm1hZG9zX20pKQoKI0p1bnRhciBhcyB0YWJlbGFzIGUgYWRpY2lvbmFyIGNvbHVuYSBjb20gZGF0YQppbmNpZGVuY2lhX2dlbmVybyA8LSBjYmluZChjb3ZpZDE5cHQkZGF0YSwgZmVtaW5pbm9zX3RvdGFsX25vdm9zLCBtYXNjdWxpbm9zX3RvdGFsX25vdm9zKQpuYW1lcyhpbmNpZGVuY2lhX2dlbmVybykgPSBjKCJEYXRhIiwgIkZlbWluaW5vIiwgIk1hc2N1bGlubyIpCgojRmF6ZXIgbWVsdCBwYXJhIGZhemVyIG8gZ3LDoWZpY28KaW5jaWRlbmNpYV9nZW5lcm9fbWVsdCA8LSBtZWx0KGluY2lkZW5jaWFfZ2VuZXJvLCBpZC52YXJzID0gIkRhdGEiKQpuYW1lcyhpbmNpZGVuY2lhX2dlbmVyb19tZWx0KSA9IGMoIkRhdGEiLCAiR2VuZXJvIiwgIkluY2lkZW5jaWEiKQoKIyNGYXplciBncsOhZmljbyBkZSBsaW5oYXMgY29tIGRhdGEgbm8gZWl4byBkbyB4LCBpbmNpZGVuY2lhIG5vIGVpeG8gZG8geSBlIGfDqW5lcm8gbmFzIGNvcmVzIGRhcyBsaW5oYXMKaW5jaWRlbmNpYV9nZW5lcm9fZ3JhZmljbyA8LSBnZ3Bsb3QoaW5jaWRlbmNpYV9nZW5lcm9fbWVsdCwgYWVzKHggPSBEYXRhLCB5ID0gSW5jaWRlbmNpYSwgY29sb3IgPSBHZW5lcm8pKSArCiAgZ2VvbV9saW5lKHNpemUgPSAwLjUpICsKICBnZW9tX3BvaW50KHNpemUgPSAwLjEsIGFlcyh0ZXh0ID0gcGFzdGUoICdEYXRhOiAnLCBEYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+R8OpbmVybzogJywgR2VuZXJvLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+SW5jaWTDqm5jaWEgOicsIEluY2lkZW5jaWEpKSkgKwogIGxhYnMoeCA9ICIiKSArCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9OCwgY29sb3IgPSAiYmxhY2siKSwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTEyLCBjb2xvciA9ICJibGFjayIpKSArCiAgc2NhbGVfeF9kYXRlKGJyZWFrcyA9ICIzIG1vbnRocyIsIGRhdGVfbGFiZWxzID0gIiViICVkIikKICAKI1Rvcm5hciBncsOhZmljbyBpbnRlcmF0aXZvCmdncGxvdGx5KGluY2lkZW5jaWFfZ2VuZXJvX2dyYWZpY28sIHRvb2x0aXAgPSAidGV4dCIgKSAlPiUgCiAgbGF5b3V0KHlheGlzID0gbGlzdCh0aXRsZSA9IHBhc3RlMChjKHJlcCgiJm5ic3A7IiwgMjApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSW5jaWTDqm5jaWEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXAoIiZuYnNwOyIsIDIwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCJcbiZuYnNwOyIsIDIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlID0gIiIpKSwKICAgICAgICAgbGVnZW5kID0gbGlzdCh4ID0gMSwgeSA9IDApKQpgYGAKCiMjIyMgRXZvbHXDp8OjbyBkYSBUYXhhIGRlIEluY2lkw6puY2lhIHBvciBHw6luZXJvCgo8YnI+CgpDb20gYSBhbsOhbGlzZSBkZXN0ZSBncsOhZmljbyBwb2RlbW9zIHZlcmlmaWNhciBxdWUgbsOjbyBleGlzdGVtIGRpZmVyZW7Dp2FzIGFjZW50dWFkYXMgZW50cmUgb3MgZ8OpbmVyb3MsIG1lc21vIHRlbmRvIGVtIGNvbnRhIGEgcHJvcG9yw6fDo28gZGUgaW5kaXbDrWR1b3MgZGUgY2FkYSBnw6luZXJvLgoKYGBge3IsIHdhcm5pbmc9RkFMU0V9CiNWYXJpw6F2ZWlzIGNvbSBhIHBvcHVsYcOnw6NvIHRvdGFsLCBmZW1pbmluYSBlIG1hc2N1bGluYSBjb20gYmFzZSBubyBJTkUKcG9wdWxhY2FvX3B0ID0gMTAyOTU5MDkKbXVsaGVyZXNfcHQgPSA1NDM1OTMyCmhvbWVuc19wdCA9IDQ4NTk5NzcKCiNDw6FsY3VsbyBkYSBpbmNpZMOqbmNpYSBjcmlhbmRvIHVtYSB0YWJiZWxhIHBhcmEgbyB0b3RhbCwgb3V0cmEgcGFyYSBtdWxoZXJlcyBlIG91dHJhIHBhcmEgaG9tZW5zCmluY2lkZW5jaWFfdG90YWwgPC0gYXMuZGF0YS5mcmFtZShjb3ZpZDE5cHQkY29uZmlybWFkb3Nfbm92b3MvIChwb3B1bGFjYW9fcHQgLSBjb3ZpZDE5cHQkY29uZmlybWFkb3MgLSBjb3ZpZDE5cHQkb2JpdG9zKSkKaW5jaWRlbmNpYV9ob21lbnMgPC0gYXMuZGF0YS5mcmFtZSgoY292aWQxOXB0JGNvbmZpcm1hZG9zX20gLSBsYWcoY292aWQxOXB0JGNvbmZpcm1hZG9zX20pKSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvIChob21lbnNfcHQgLSBjb3ZpZDE5cHQkY29uZmlybWFkb3NfbSkpIAppbmNpZGVuY2lhX211bGhlcmVzIDwtIGFzLmRhdGEuZnJhbWUoKGNvdmlkMTlwdCRjb25maXJtYWRvc19mIC0gbGFnKGNvdmlkMTlwdCRjb25maXJtYWRvc19mKSkgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvIChtdWxoZXJlc19wdCAtIGNvdmlkMTlwdCRjb25maXJtYWRvc19mKSkKCiNSZW1vdmVyIHZhbG9yZXMgbmVnYXRpdm9zIGRldmlkbyBhIGVycm8gbmEgYmFzZSBkZSBkYWRvcyBvcmlnaW5hbCBlbSBxdWUgdmFsb3IgY3VtdWxhdGl2byBkbyBuw7ptZXJvIGNhc29zIGhvbWVucyBlIG11bGhlcmVzIGVyYSAwIGUgbsOjbyBkZXZpYQppbmNpZGVuY2lhX2hvbWVuc1sxNzQ6MTc1LF0gPC0gTkEKaW5jaWRlbmNpYV9tdWxoZXJlc1sxNzQ6MTc1LF0gPC0gTkEKCiNDcmlhciB1bWEgdGFiZWxhIGNvbSBhcyAzIHRhYmVsYXMgYW50ZXJpb3JlcywgYWRpY2lvbmFuZG8gdW1hIGNvbHVuYSBjb20gYSBkYXRhIGUgbXVkYXIgb3Mgbm9tZXMgZGFzIGNvbHVuYXMKaW5jaWRlbmNpYSA8LSBkYXRhLmZyYW1lKGNvdmlkMTlwdCRkYXRhLCBpbmNpZGVuY2lhX3RvdGFsKjEwMCwgaW5jaWRlbmNpYV9tdWxoZXJlcyoxMDAsIGluY2lkZW5jaWFfaG9tZW5zKjEwMCkKbmFtZXMoaW5jaWRlbmNpYSkgPC0gYygiRGF0YSIsICJUb3RhbCIsICJNdWxoZXJlcyIsICJIb21lbnMiKQoKI0ZhemVyIG1lbHQgcGFyYSBwb2RlciBmYXplciBncsOhZmljbyBkZSBsaW5oYXMgZSBkYXIgbm9tZSDDoCBjb2x1bmEgZG8gZ8OpbmVybwppbmNpZGVuY2lhX21lbHQgPC0gbWVsdChpbmNpZGVuY2lhLCBpZC52YXJzID0gIkRhdGEiKQpuYW1lcyhpbmNpZGVuY2lhX21lbHQpIDwtIGMoIkRhdGEiLCAiR2VuZXJvIiwgIkluY2lkZW5jaWEiKQoKI0ZhemVyIGdyw6FmaWNvIGRlIGxpbmhhcyBjb20gZGF0YSBubyBlaXhvIGRvIHgsIGEgaW5jaWRlbmNpYSBubyBlaXhvIGRvIHkgZSBvIGfDqW5lcm8gZW0gY2FkYSBsaW5oYQpnZ3Bsb3QoaW5jaWRlbmNpYV9tZWx0LCBhZXMoeCA9IERhdGEsIHkgPSBJbmNpZGVuY2lhLCBjb2xvciA9IEdlbmVybykpICsKICBnZW9tX3BvaW50KHNpemUgPSAwLjQpICsKICBnZW9tX2xpbmUoc2l6ZSA9IDAuNCkgKwogIGZhY2V0X2dyaWQoaW5jaWRlbmNpYV9tZWx0JEdlbmVybykgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogIGxhYnMoeCA9ICIiLCAKICAgICAgIHkgPSJUYXhhIGRlIEluY2lkw6puY2lhICglKSIpICsKICB0aGVtZShheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgICAgc3RyaXAudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4LCBhbmdsZSA9IDApKSArCiAgc2NhbGVfeF9kYXRlKGJyZWFrcyA9ICIzIG1vbnRocyIsIGRhdGVfbGFiZWxzID0gIiViICVkIikKICAgICAgCmBgYAoKPGJyPgoKIyMgKipNb3J0ZXMqKiB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30KKioqCgpOZXN0ZSB0w7NwaWNvIHZhbW9zIGFib3JkYXIgYSBtb3J0YWxpZGFkZSBlbSB2YWxvciBhYnNvbHV0byAobsO6bWVybyBkZSBtb3J0ZXMpLCBhIHRheGEgZGUgbW9ydGFsaWRhZGUgKG7Dum1lcm8gdG90YWwgZGUgbW9ydGVzL3BvcHVsYcOnw6NvIHRvdGFsKSBlIHRheGEgZGUgbGV0YWxpZGFkZSAobsO6bWVybyB0b3RhbCBkZSBtb3J0ZXMvcG9wdWxhw6fDo28gaW5mZXRhZGEpLgoKPGJyPgoKIyMjIE1vcnRhbGlkYWRlIHsudGFic2V0fQoKIyMjIyBSZWxhw6fDo28gY29tIGEgRXZvbHXDp8OjbyBkYSBJbmNpZMOqbmNpYQo8YnI+CgpBIGV2b2x1w6fDo28gZG8gbsO6bWVybyBkZSBtb3J0ZXMgZGnDoXJpYXMgdGVuZGUgYSBhY29tcGFuaGFyIGEgZXZvbHXDp8OjbyBkbyBuw7ptZXJvIGRlIGNhc29zIGRpw6FyaW9zLiBJbmljaWFsbWVudGUsIGNvbW8gb3MgY2Fzb3MgZGlhZ25vc3RpY2Fkb3MgZXJhbSBtYWlzIGdyYXZlcywgb3MgcGFjaWVudGVzIG1vcnJpYW0gbWFpcyBjZWRvIGUgcG9yIGVzc2EgcmF6w6NvIG8gZGVzZmFzYW1lbnRvIGVudHJlIG9zIGNhc29zIGUgYXMgbW9ydGVzIG7Do28gZXJhIHTDo28gYWNlbnR1YWRvLiBDb20gYSBldm9sdcOnw6NvIGRhIHBhbmRlbWlhLCBjb21lw6dvdSBhIHNlciBmZWl0byB1bSBkaWFnbsOzc3RpY28gbWFpcyBwcmVjb2NlLCBvIHF1ZSBhdW1lbnRvdSBvIGludGVydmFsbyBlbnRyZSBvIGRpYWduw7NzdGljbyBlIGEgbW9ydGUuIAoKRGUgZm9ybWEgZ2VyYWwsIG8gbsO6bWVybyBkZSBtb3J0ZXMgZGnDoXJpYXMgdGVtIHZpbmRvIGEgZGVjcmVzY2VyLiDDgCBkYXRhIGRhIGFuw6FsaXNlLCBwb2RlbW9zIHZlcmlmaWNhciBxdWUgbWVzbW8gcGVyYW50ZSB1bSBncmFuZGUgYXVtZW50byBubyBuw7ptZXJvIGRlIGNhc29zIGRpw6FyaW9zLCBvIG7Dum1lcm8gZGUgbW9ydGVzIG7Do28gdGVtIGFjb21wYW5oYWRvIGVzdGUgYXVtZW50by4gSXN0byBwb2RlIGRldmVyLXNlIGEgdW0gbWFpb3IgY29uaGVjaW1lbnRvIHNvYnJlIGEgZG9lbsOnYSwgw6AgbWFpb3IgaW5jaWTDqm5jaWEgbmFzIGZhaXhhcyBldMOhcmlhcyBtYWlzIGpvdmVucyBlLCB0YWx2ZXosIHVtYSBtZW5vciB2aXJ1bMOqbmNpYSBkbyB2w61ydXMuCgpgYGB7ciwgd2FybmluZz1GQUxTRX0KI0ZhemVyIHRhYmVsYSBjb20gY29sdW5hIHBhcmEgZGF0YSBlIG91dHJhIHBhcmEgw7NiaXRvcyBvY29ycmlkb3MgZW0gY2FkYSBkaWEKbW9ydGVzX2RpYXJpYXMgPC0gYXMuZGF0YS5mcmFtZShjYmluZChjb3ZpZDE5cHQkZGF0YSwgYXMuZGF0YS5mcmFtZShjb3ZpZDE5cHQkb2JpdG9zIC0gbGFnKGNvdmlkMTlwdCRvYml0b3MpKSkpCm5hbWVzKG1vcnRlc19kaWFyaWFzKSA9IGMoIkRhdGEiLCAiTW9ydGVzIikKCiNUYWJlbGEgY29tIGNvbHVuYSBwYXJhIGRhdGEsIG91dHJhIHBhcmEgY2Fzb3MgZSBvdXRyYSBwYXJhIG1vcnRlcwpjYXNvc19tb3J0ZXNfZGlhcmlvcyA8LSBtZXJnZShjYXNvc19kaWFyaW9zLCBtb3J0ZXNfZGlhcmlhcywgYnk9IkRhdGEiKQoKI0ZhemVyIG1lbHQgcGFyYSBwb2RlciBmYXplciBncsOhZmljbyBkZSBsaW5oYXMKY2Fzb3NfbW9ydGVzX2RpYXJpb3NfbWVsdCA8LSBtZWx0KGNhc29zX21vcnRlc19kaWFyaW9zLCBpZC52YXJzID0gIkRhdGEiKQoKI0ZhemVyIGdyw6FmaWNvIGRlIGxpbmhhcyBjb20gZGF0YSBubyBlaXhvIGRvIHgsIG7Dum1lcm8gbm8gZWl4byBkbyB5IGUgbW9ydGVzIG91IGNhc29zIGVtIGNhZGEgbGluaGEKZ2dwbG90KGNhc29zX21vcnRlc19kaWFyaW9zX21lbHQsIGFlcyh4ID0gRGF0YSwgeSA9IHZhbHVlLCBjb2xvciA9IHZhcmlhYmxlKSkgKwogIGdlb21fbGluZShzaXplID0gMSkgKwogIGZhY2V0X2dyaWQoY2Fzb3NfbW9ydGVzX2RpYXJpb3NfbWVsdCR2YXJpYWJsZSwgc2NhbGVzID0gImZyZWVfeSIpICsKICBndWlkZXMoY29sb3IgPSBGQUxTRSkgKwogIGxhYnMoeCA9ICIiLCAKICAgICAgIHkgPSAiTsO6bWVybyBkZSBQZXNzb2FzIiwKICAgICAgIGNvbG9yID0gIiIpICsKICBzY2FsZV9jb2xvcl9kaXNjcmV0ZShsYWJlbHMgPSBjKCJJbmNpZMOqbmNpYSIsICJNb3J0ZXMgRGnDoXJpYXMiKSkgKwogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4odCA9IDIwLCBiID0gMjApLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKHIgPSAyMCwgbCA9IDIwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxMikpICsKICBzY2FsZV94X2RhdGUoYnJlYWtzID0gIjMgbW9udGhzIiwgZGF0ZV9sYWJlbHMgPSAiJWIgJWQiKQpgYGAKCgojIyMjIFBvciBGYWl4YSBFdMOhcmlhIGUgcG9yIEfDqW5lcm8KCjxicj4KCk5lc3RlIGdyw6FmaWNvIGRlIGJhcnJhcyDDqSBmYWNpbG1lbnRlIHZpc8OtdmVsIHF1ZSBhdMOpIGFvcyAzOSBhbm9zIG8gbsO6bWVybyBkZSBtb3J0ZXMgw6kgcXVhc2UgaW5leGlzdGVudGUuIENvbWXDp2EgYSBhdW1lbnRhciBkZSBmb3JtYSBtYWlzIHNpZ25pZmljYXRpdmEgYSBwYXJ0aXIgZG9zIDU5IGFub3MgKG8gcXVlIGNvbmZpcm1hIHF1ZSBzZSB0cmF0YSBkYSBwb3B1bGHDp8OjbyBkZSByaXNjbyksIHNlbmRvIGEgZmFpeGEgZXTDoXJpYSBkb3MgODArIGFub3MgYXF1ZWxhIHF1ZSB0ZW0sIGRlIGxvbmdlLCBvIG1haW9yIG7Dum1lcm8gZGUgbW9ydGVzLiAKCsOJIHBlcmNlcHTDrXZlbCB0YW1iw6ltIHF1ZSBvIGfDqW5lcm8gbWFzY3VsaW5vIHRlbSBtYWlvciBuw7ptZXJvIGRlIG1vcnRlcywgYW8gbG9uZ28gZGUgdG9kYXMgYXMgZmFpeGFzIGV0w6FyaWFzIGV4ZWN0byBuYSBmYWl4YSBldMOhcmlhIGRvcyA4MCsuIFBhcmEgZXN0ZXMgZGFkb3Mgc2VyZW0gZXN0YXRpc3RpY2FtZW50ZSBmacOhdmVpcywgZXJhIG5lY2Vzc8OhcmlvIHRlci1zZSB0aWRvIGVtIGNvbnRhIGEgcHJvcG9yw6fDo28gZGUgcGVzc29hcyBjb25maXJtYWRhcyBkb3MgZ8OpbmVyb3MgbWFzY3VsaW5vIGUgZmVtaW5pbm8gZXhpc3RlbnRlcyBlbSBjYWRhIGZhaXhhIGV0w6FyaWEgZGEgcG9wdWxhw6fDo28uIE5vIGVudGFudG8sIHNhYmVtb3MgcXVlIGVtIFBvcnR1Z2FsIGEgZXNwZXJhbsOnYSBtw6lkaWEgZGUgdmlkYSDDqSBzdXBlcmlvciBuYXMgbXVsaGVyZXMgZG8gcXVlIG5vcyBob21lbnMsIG8gcXVlIHByZXNzdXDDtWUgcXVlIGV4aXN0ZW0gbWFpcyBtdWxoZXJlcyBuYSBmYWl4YSBldMOhcmlhIGRvcyA4MCsganVzdGlmaWNhbmRvLCBhc3NpbSwgdW0gbWFpb3IgbsO6bWVybyBkZSBtb3J0ZXMgZG8gZ8OpbmVybyBmZW1pbmlubyBuZXN0ZSBncnVwbyBldMOhcmlvLgoKYGBge3IsIHdhcm5pbmc9RkFMU0V9CiNTZWxlY2lvbmFyIGFzIGNvbHVuYXMgZGUgb2JpdG9zIGZlbWluaW5vIHBhcmEgdG9kYXMgYXMgaWRhZGVzIGUganVudMOhLWxhcyBudW1hIHRhYmVsYSBlIGZhemVyIG8gbWVzbW8gcGFyYSBvIG1hc2N1bGlubwpmZW1pbmlub3NfbW9ydGVzIDwtIGFzLmRhdGEuZnJhbWUoY292aWQxOXB0ICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6OnNlbGVjdChzdGFydHNfd2l0aCgib2JpdG9zXyIpICYgKGVuZHNfd2l0aCgiOV9mIil8IGVuZHNfd2l0aCgicGx1c19mIikpKSkKbWFzY3VsaW5vc19tb3J0ZXMgPC0gYXMuZGF0YS5mcmFtZShjb3ZpZDE5cHQgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6OnNlbGVjdCgoc3RhcnRzX3dpdGgoIm9iaXRvc18iKSAmIChlbmRzX3dpdGgoIjlfbSIpfCBlbmRzX3dpdGgoInBsdXNfbSIpKSkpKQoKI1NlbGVjaW9uYXIgbyB2YWxvciBtYWlzIHJlY2VudGUgZGUgY2FkYSBjb2x1bmEgZGUgbW9kbyBhIGZpY2FyIGNvbSBvIG7Dum1lcm8gZGUgw7NiaXRvcyBhdMOpIGFvIG1vbWVudG8gIHBhcmEgY2FkYSBmYWl4YSBldMOhcmlhIGUgcGFyYSBjYWRhIGfDqW5lcm8KbW9ydGVzX2ZlbWluaW5vc19pZGFkZSA8LSBhcy5kYXRhLmZyYW1lKGxhcHBseShmZW1pbmlub3NfbW9ydGVzLCBsYXN0KSkKbW9ydGVzX21hc2N1bGlub3NfaWRhZGUgPC0gYXMuZGF0YS5mcmFtZShsYXBwbHkobWFzY3VsaW5vc19tb3J0ZXMsIGxhc3QpKQoKI0NyaWFyIHRhYmVsYSBjb20gdW1hIGNvbHVuZGEgcGFyYSBhIGZhaXhhIGV0w6FyaWEgZSBvdXRyYSBwYXJhIG8gbsO6bWVybyBkZSDDs2JpdG9zIGZlbWluaW5vcyBlIG11ZGFyIGNvbHVuYSBkYSAgZmFpeGEgZXTDoXJpYSBwYXJhIG9zIG5vbWVzIGFkZXF1YWRvcwptb3J0ZXNfZmVtaW5pbm9zX2lkYWRlX2ludmVydGlkbyA8LSBhcy5kYXRhLmZyYW1lKHQobW9ydGVzX2ZlbWluaW5vc19pZGFkZSkpJT4lIAogIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAiSWRhZGUiKQpuYW1lcyhtb3J0ZXNfZmVtaW5pbm9zX2lkYWRlX2ludmVydGlkbylbMl0gPC0gIkZlbWluaW5vIgptb3J0ZXNfZmVtaW5pbm9zX2lkYWRlX2ludmVydGlkb1ssMV0gPC0gYygiMC05IiwgIjEwLTE5IiwgIjIwLTI5IiwgIjMwLTM5IiwgIjQwLTQ5IiwgIjUwLTU5IiwgIjYwLTY5IiwgIjcwLTc5IiwgIjgwKyIpCgojQ3JpYXIgdGFiZWxhIGNvbSB1bWEgY29sdW5kYSBwYXJhIGEgZmFpeGEgZXTDoXJpYSBlIG91dHJhIHBhcmEgbyBuw7ptZXJvIGRlIMOzYml0b3MgbWFzY3VsaW5vcyBlIG11ZGFyIGNvbHVuYSBkYSBmYWl4YSBldMOhcmlhIHBhcmEgb3Mgbm9tZXMgYWRlcXVhZG9zCm1vcnRlc19tYXNjdWxpbm9zX2lkYWRlX2ludmVydGlkbyA8LSBhcy5kYXRhLmZyYW1lKHQobW9ydGVzX21hc2N1bGlub3NfaWRhZGUpKSAlPiUgCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJJZGFkZSIpCm5hbWVzKG1vcnRlc19tYXNjdWxpbm9zX2lkYWRlX2ludmVydGlkbylbMl0gPC0gIk1hc2N1bGlubyIKbW9ydGVzX21hc2N1bGlub3NfaWRhZGVfaW52ZXJ0aWRvWywxXSA8LSBjKCIwLTkiLCAiMTAtMTkiLCAiMjAtMjkiLCAiMzAtMzkiLCAiNDAtNDkiLCAiNTAtNTkiLCAiNjAtNjkiLCAiNzAtNzkiLCAiODArIikKCiNKdW50YXIgYXMgMyB0YWJlbGFzIHF1ZSBjcmnDoW1vcwptb3J0ZXNfZmVtX21hc2MgPC0gbWVyZ2UobW9ydGVzX2ZlbWluaW5vc19pZGFkZV9pbnZlcnRpZG8sIG1vcnRlc19tYXNjdWxpbm9zX2lkYWRlX2ludmVydGlkbywgYnkgPSAiSWRhZGUiKQoKI0ZhemVyIG1lbHQgcGFyYSBwb2RlciBmYXplciBncsOhZmljbyAKbW9ydGVzX2ZlbV9tYXNjX21lbHQgPC0gbWVsdChtb3J0ZXNfZmVtX21hc2MsIGlkLnZhcnMgPSAiSWRhZGUiKQpuYW1lcyhtb3J0ZXNfZmVtX21hc2NfbWVsdCkgPSBjKCJJZGFkZSIsICJHZW5lcm8iLCAiTW9ydGVzIikKCiNGYXplciBncsOhZmljbyBkZSBiYXJyYXMgY29tIGlkYWRlIG5vIGVpeG8gZG8geCwgbyBuw7ptZXJvIGRlIMOzYml0b3Mgbm8gZWl4byBkbyB5IGUgbyBnw6luZXJvIGVtIGNhZGEgYmFycmEKbW9ydGVzX2ZlbV9tYXNjX2dyYWZpY28gPC0gZ2dwbG90KG1vcnRlc19mZW1fbWFzY19tZWx0LCBhZXMoeCA9IElkYWRlLCB5ID0gTW9ydGVzLCBmaWxsID0gR2VuZXJvKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIiwgYWVzKHRleHQgPSBwYXN0ZSggJ0ZhaXhhIEV0w6FyaWE6ICcsIElkYWRlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+R8OpbmVybzogJywgR2VuZXJvLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+TsK6IGRlIG1vcnRlcyA6JywgTW9ydGVzKSkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkgKwogIGNvb3JkX2NhcnRlc2lhbiggeWxpbSA9IGMoMCwgbWF4KG1vcnRlc19mZW1fbWFzY19tZWx0JE1vcnRlcyArIDEwMCkpKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICBsYWJzKHggPSAiIiwKICAgICAgIHkgPSAiTW9ydGVzIikgKwogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTgsIGNvbG9yID0gImJsYWNrIiksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMiwgY29sb3IgPSAiYmxhY2siKSkgKwogIGd1aWRlcyhmaWxsPWd1aWRlX2xlZ2VuZCh0aXRsZT0iZ8OpbmVybyIpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiZGVlcHBpbmszIiwgImxpZ2h0Ymx1ZSIsICJncmV5NjAiKSkKCiNUb3JuYXIgZ3LDoWZpY28gaW50ZXJhdGl2bwpnZ3Bsb3RseShtb3J0ZXNfZmVtX21hc2NfZ3JhZmljbywgdG9vbHRpcCA9ICJ0ZXh0IikgJT4lIAogIGxheW91dCh5YXhpcyA9IGxpc3QodGl0bGUgPSBwYXN0ZTAoYyhyZXAoIiZuYnNwOyIsIDIwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk7Dum1lcm8gZGUgTW9ydGVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCImbmJzcDsiLCAyMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcCgiXG4mbmJzcDsiLCAyKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xsYXBzZSA9ICIiKSksCiAgICAgICAgIGxlZ2VuZCA9IGxpc3QoeCA9IDEsIHkgPSAwKSkKYGBgCgoKIyMjIyBQb3IgQVJTCgo8YnI+CgpOZXN0ZSBncsOhZmljbyBkZSBiYXJyYXMgZSBubyBtYXBhIHZlbW9zIHF1ZSBhIEFSUyBjb20gbWFpb3IgbsO6bWVybyBkZSBtb3J0ZXMgw6kgYSBOb3J0ZSwgc2VndWlkYSBkZSBMaXNib2EgZSBWYWxlIGRvIFRlam8uIMOJIGltcG9ydGFudGUgcmVhbMOnYXIgcXVlIGVzdGUgbsO6bWVybyDDqSBhYnNvbHV0bywgbG9nbywgbsOjbyB0ZW0gZW0gY29uc2lkZXJhw6fDo28gYSBwcm9wb3LDp8OjbyBkZSBpbmZldGFkb3MgZGUgY2FkYSBBUlMuCgpgYGB7ciwgd2FybmluZz1GQUxTRX0KI0NyaWFyIHRhYmVsYSBjb20gdW1hIGNvbHVuYSBwYXJhIGFzIFJlZ2nDo29lcyBlIG91dHJhIHBhcmEgbyBuw7ptZXJvIG1haXMgcmVjZW50ZSB0b3RhbCBkZSDDs2JpdG9zIGUgZGFyIG5vbWVzCm1vcnRvc19yZWdpb2VzIDwtIGFzLmRhdGEuZnJhbWUodChhcy5kYXRhLmZyYW1lKGxhcHBseShjb3ZpZDE5cHRbLG9iaXRvc19hcnNub3J0ZTpvYml0b3NfbWFkZWlyYV0sIGxhc3QpKSkpICU+JSAKICByb3duYW1lc190b19jb2x1bW4odmFyID0gIlJlZ2lvZXMiKQpuYW1lcyhtb3J0b3NfcmVnaW9lcylbMl0gPC0gIk1vcnRlcyIKbW9ydG9zX3JlZ2lvZXNbLCAxXSA8LSBjKCJOb3J0ZSIsICJDZW50cm8iLCAiTFZUIiwgIkFsZW50ZWpvIiwgIkFsZ2FydmUiLCAiQcOnb3JlcyIsICJNYWRlaXJhIikKCiNGYXplciBncsOhZmljbyBjb20gUmVnacOjb2VzIG5vIGVpeG8gZG8geCBlIG7Dum1lcm8gZGUgbW9ydGVzIG5vIGVpeG8gZG8geQptb3J0b3NfcmVnaW9lc19ncmFmaWNvIDwtIGdncGxvdChtb3J0b3NfcmVnaW9lcywgYWVzKHggPSBSZWdpb2VzLCB5ID0gTW9ydGVzKSkgKwogIGdlb21fY29sKGZpbGwgPSAic2FsbW9uMSIsIHdpZHRoID0gMC41LCBhZXModGV4dCA9IHBhc3RlKCAnQVJTOiAnLCBSZWdpb2VzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+TsK6IGRlIG1vcnRlcyA6JywgTW9ydGVzKSkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkgKwogIGxhYnMoeCA9ICIiKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSkKCm1vcnRvc19yZWdpb2VzX2dyYWZpY29faW50ZXJhdGl2byA8LSBnZ3Bsb3RseShtb3J0b3NfcmVnaW9lc19ncmFmaWNvLCB0b29sdGlwID0gInRleHQiKSAlPiUgCiAgbGF5b3V0KHlheGlzID0gbGlzdCh0aXRsZSA9IHBhc3RlMChjKHJlcCgiJm5ic3A7IiwgMjApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTsO6bWVybyBkZSBNb3J0ZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXAoIiZuYnNwOyIsIDIwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCJcbiZuYnNwOyIsIDIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlID0gIiIpKSkKCiNtYXBhCiNEYSB0YWJlbGEgYW50ZXJpb3IgY29tIHRvZGFzIGFzIGRhdGFzLCBzZWxlY2lvbmFyIGFwZW5hcyBvIHZhbG9yIG1haXMgcmVjZW50ZSBlIG11ZGFyIG5vbWUgY29sdW5hIGUgUmVnacOjb2VzCmluY2lkZW5jaWFfcmVnaW9lc19vcmRlbSA8LSBhcy5kYXRhLmZyYW1lKHQoYXMuZGF0YS5mcmFtZShsYXBwbHkoaW5jaWRlbmNpYV9yZWdpb2VzWyxjKDUsIDYsIDcsIDMsIDgsIDIsIDQpXSwgbGFzdCkpKSkgJT4lIAogIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAiUmVnaWFvIikgCmluY2lkZW5jaWFfcmVnaW9lc19vcmRlbVssMV0gPC0gYygiQWxlbnRlam8iLCAiQWxnYXJ2ZSIsICJBw6dvcmVzIiwiQ2VudHJvIiwgIk1hZGVpcmEiLCAiTm9ydGUiLCAiTGlzYm9hIGUgVmFsZSBkbyBUZWpvIikKCiMjRGVmaW5pciBpbnRlcnZhbG9zIGRhIGxlZ2VuZGEKYmluc18zID0gIGMoMCwgMjUsIDUwLCAxMDAsIDUwMCwgMTAwMCwgSW5mKQoKIyNPcmRlbmFyIGEgdGFiZWxhIGZlaXRhIGFudGVyaW9ybWVudGUgcGFyYSBmaWNhciBjb20gYSBtZXNtYSBvcmRlbSBxdWUgb3MgcG9saWdvbm9zIGRvIG1hcGEKbW9ydG9zX3JlZ2lvZXNfb3JkZW0gPC0gbW9ydG9zX3JlZ2lvZXNbYyg0LCA1LCA2LCAyLCA3LCAxLCAzKSxdCgojI0RlZmluaXIgYSBwYWxldGUgZGUgY29yZXMKcGFsXzMgPC0gY29sb3JCaW4oIllsT3JSZCIsIGRvbWFpbiA9IG1vcnRvc19yZWdpb2VzX29yZGVtWywyXSwgYmlucyA9IGJpbnNfMykKCiMjRGVmaW5pciBhIGxlZ2VuZGEgcXVhbmRvIHNlIHBhc3NhIGNvbSBvIHJhdG8gcG9yIGNpbWEKbGFiZWxzXzMgPC0gc3ByaW50ZigKICAiPHN0cm9uZz4lczwvc3Ryb25nPjxici8+JWcgTW9ydG9zIiwKICBpbmNpZGVuY2lhX3JlZ2lvZXNfb3JkZW1bLDFdLCBtb3J0b3NfcmVnaW9lc19vcmRlbVssMl0KKSAlPiUgbGFwcGx5KGh0bWx0b29sczo6SFRNTCkKCiMjRmF6ZXIgbyBtYXBhCm1vcnRvc19yZWdpb2VzX21hcGEgPC0gbGVhZmxldChtYXBhX3B0KSAlPiUgCiAgYWRkVGlsZXMoZ3JvdXAgPSAiTm9ybWFsIikgJT4lIAogIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJENhcnRvREIuUG9zaXRyb24sIGdyb3VwID0gIkNsYXJvIikgJT4lIAogIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJENhcnRvREIuRGFya01hdHRlck5vTGFiZWxzLCBncm91cCA9ICJFc2N1cm8iKSAlPiUgCiAgYWRkTGF5ZXJzQ29udHJvbCgKICAgIGJhc2VHcm91cHMgPSBjKCJOb3JtYWwiLCAiQ2xhcm8iLCAiRXNjdXJvIiksCiAgICBvcHRpb25zID0gbGF5ZXJzQ29udHJvbE9wdGlvbnMoY29sbGFwc2VkID0gVFJVRSkKICApICU+JSAKICBhZGRQb2x5Z29ucygKICAgIGZpbGxDb2xvciA9IH5wYWxfMyhtb3J0b3NfcmVnaW9lc19vcmRlbVssMl0pLCAKICAgIHdlaWdodCA9IDIsCiAgICBvcGFjaXR5ID0gMSwKICAgIGNvbG9yID0gIndoaXRlIiwKICAgIGRhc2hBcnJheSA9ICIzIiwKICAgIGZpbGxPcGFjaXR5ID0gMC43LAogICAgaGlnaGxpZ2h0ID0gaGlnaGxpZ2h0T3B0aW9ucygKICAgICAgd2VpZ2h0ID0gNSwKICAgICAgY29sb3IgPSAiIzY2NiIsCiAgICAgIGRhc2hBcnJheSA9ICIiLAogICAgICBmaWxsT3BhY2l0eSA9IDAuNywKICAgICAgYnJpbmdUb0Zyb250ID0gVFJVRSksCiAgICBsYWJlbCA9IGxhYmVsc18zLAogICAgbGFiZWxPcHRpb25zID0gbGFiZWxPcHRpb25zKHN0eWxlID0gbGlzdCgiZm9udC13ZWlnaHQiID0gIm5vcm1hbCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWRkaW5nID0gIjNweCA4cHgiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0c2l6ZSA9ICIxNXB4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXJlY3Rpb24gPSAiYXV0byIpKSAlPiUgCiAgYWRkTGVnZW5kKHBhbCA9IHBhbF8zLCB2YWx1ZXMgPSBpbmNpZGVuY2lhX3JlZ2lvZXNfb3JkZW1bLDJdLCBvcGFjaXR5ID0gMC43LCB0aXRsZSA9ICJOw7ptZXJvIGRlIE1vcnRlcyBwb3IgQVJTIiwKICAgICAgICAgICAgcG9zaXRpb24gPSAiYm90dG9tcmlnaHQiKQoKYnJvd3NhYmxlKAogIHRhZ0xpc3QobGlzdCgKICAgIHRhZ3MkZGl2KAogICAgICBzdHlsZSA9ICd3aWR0aDo1MCU7ZGlzcGxheTpibG9jaztmbG9hdDpsZWZ0OycsCiAgICAgIG1vcnRvc19yZWdpb2VzX21hcGEKICAgICksCiAgICB0YWdzJGRpdigKICAgICAgc3R5bGUgPSAnd2lkdGg6NTAlO2Rpc3BsYXk6YmxvY2s7ZmxvYXQ6bGVmdDsnLAogICAgICBtb3J0b3NfcmVnaW9lc19ncmFmaWNvX2ludGVyYXRpdm8KICAgICkKICApKQopCmBgYAoKCiMjIyBUYXhhIGRlIE1vcnRhbGlkYWRlIHsudGFic2V0fQoKIyMjIyBQb3IgR8OpbmVybwoKPGJyPgoKTmVzdGUgZ3LDoWZpY28gZGUgYmFycmFzIHBvZGVtb3MgdmVyIHF1ZSBvcyBob21lbnMgdMOqbSB1bWEgdGF4YSBkZSBtb3J0YWxpZGFkZSBzdXBlcmlvciDDoCBkYXMgbXVsaGVyZXMuIENvbnR1ZG8sIGVzdGUgZ3LDoWZpY28gbsOjbyB0ZW0gZW0gY29udGEgc2UgZXhpc3RlbSBtYWlzIHBlc3NvYXMgZG8gZ8OpbmVybyBtYXNjdWxpbm8gaW5mZXRhZGFzIGRvIHF1ZSBkbyBnw6luZXJvIGZlbWluaW5vLgoKYGBge3IsIHdhcm5pbmc9RkFMU0V9CiNDw6FsY3VsbyBkYSBtb3J0YWxpZGFkZSB0b3RhbCwgZmVtaW5pbmEgZSBtYXNjdWxpbmEgY29tIGJhc2Ugbm8gdmFsb3IgbWFpcyByZWNlbnRlIGRvcyDDs2JpdG9zLCBxdWUgw6kgdGFtYsOpbSBvIG1haXMgYWx0bwptb3J0YWxpZGFkZV90b3RhbCA8LSBtYXgoY292aWQxOXB0JG9iaXRvcywgbmEucm0gPSBUUlVFKSAvIHBvcHVsYWNhb19wdAptb3J0YWxpZGFkZV9tdWxoZXJlcyA8LSBtYXgoY292aWQxOXB0JG9iaXRvc19mLCBuYS5ybSA9IFRSVUUpIC8gbXVsaGVyZXNfcHQKbW9ydGFsaWRhZGVfaG9tZW5zIDwtIG1heChjb3ZpZDE5cHQkb2JpdG9zX20sIG5hLnJtID1UUlVFKSAvIGhvbWVuc19wdAoKI0NyaWFyIHVtYSB0YWJlbGEgY29tIHVtYSBjb2x1bmEgcGFyYSBvIGfDqW5lcm8gZSBvdXRyYSBwYXJhIG8gdmFsb3IgZGEgbW9ydGFsaWRhZGUgZSBkYXIgbm9tZSBhcHJvcHJpYWRvIGFvcyBnZW5lcm9zCm1vcnRhbGlkYWRlIDwtIGRhdGEuZnJhbWUodChkYXRhLmZyYW1lKG1vcnRhbGlkYWRlX3RvdGFsLCBtb3J0YWxpZGFkZV9tdWxoZXJlcywgbW9ydGFsaWRhZGVfaG9tZW5zKSkpICU+JSAKICByb3duYW1lc190b19jb2x1bW4odmFyID0gImdlbmVybyIpCm5hbWVzKG1vcnRhbGlkYWRlKVsyXSA8LSAibW9ydGFsaWRhZGUiCm1vcnRhbGlkYWRlWywgMV0gPC0gYygiVG90YWwiLCAiTXVsaGVyZXMiLCAiSG9tZW5zIikKCiNDcmlhciB1bSBncsOhZmljbyBkZSBiYXJyYXMgY29tIG8gZ2VuZXJvIG5vIGVpeG8gZG8geCBlIGEgbW9ydGFsaWRhZGUgbm8gZWl4byBkbyB5CmdncGxvdChtb3J0YWxpZGFkZSwgYWVzKHggPSBnZW5lcm8sIHkgPSBtb3J0YWxpZGFkZSoxMDApKSArCiAgZ2VvbV9jb2woZmlsbCA9ICJzYWxtb24xIiwgd2lkdGggPSAwLjUpICsKICBjb29yZF9jYXJ0ZXNpYW4oIHlsaW0gPSBjKDAsIG1heChtb3J0YWxpZGFkZSRtb3J0YWxpZGFkZSoxMDYpKSkgKwogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsIDApKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICBsYWJzKHggPSAiIiwKICAgICAgIHkgPSAiVGF4YSBkZSBNb3J0YWxpZGFkZSAoJSkiKSArCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbih0ID0gMjAsIGIgPSAyMCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMTIpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4ociA9IDIwLCBsID0gMjApLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTEyLCBjb2xvciA9ICJibGFjayIpLAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTIsIGNvbG9yID0gImJsYWNrIikpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gc2NhbGVzOjpwZXJjZW50KG1vcnRhbGlkYWRlLCBkaWdpdHMgPSA0KSksIAogICAgICAgICAgICB2anVzdCA9IC0wLjUsIAogICAgICAgICAgICBzaXplID0gNCkKYGBgCgoKIyMjIyBQb3IgRmFpeGEgRXTDoXJpYQoKTmVzdGUgZ3LDoWZpY28gZGUgYmFycmFzIMOpIHBvc3PDrXZlbCB2ZXJpZmljYXIgcXVlIGEgdGF4YSBkZSBtb3J0YWxpZGFkZSBhdW1lbnRhIGNvbSBvIGF1bWVudG8gZGEgaWRhZGUuIElzdG8gZGVtb25zdHJhLCBtYWlzIHVtYSB2ZXosIHF1ZSBhIGlkYWRlIMOpIHVtIGltcG9ydGFudGUgZmF0b3IgZGUgcmlzY28sIGVzcGVjaWFsbWVudGUgcGFyYSBhIGZhaXhhIGV0w6FyaWEgZG9zIDgwKyBhbm9zLgoKYGBge3IsIHdhcm5pbmc9RkFMU0V9CiNDYWxjdWxhciBhIHRheGEgZGUgbW9ydGFsaWRhZGUgcGFyYSBjYWRhIGZhaXhhIGV0w6FyaWEgZSBhZGljaW9uYXIgY29sdW5hIGNvbSBmYWl4YXMgZXTDoXJpYXMKbW9ydGFsaWRhZGVfaWRhZGUgPC0gY2JpbmQobW9ydGVzX2ZlbWluaW5vc19pZGFkZV9pbnZlcnRpZG9bLDFdLCAoKG1vcnRlc19mZW1pbmlub3NfaWRhZGVfaW52ZXJ0aWRvWywyXSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgbW9ydGVzX21hc2N1bGlub3NfaWRhZGVfaW52ZXJ0aWRvWywyXSkqMTAwLyBwb3B1bGFjYW9faWRhZGVzX3B0KSkKbmFtZXMobW9ydGFsaWRhZGVfaWRhZGUpID0gYygiRmFpeGFfRXRhcmlhIiwgIlRheGFfTW9ydGFsaWRhZGUiKQoKI0ZhemVyIG8gZ3LDoWZpY28gY29tIGZhaXhhIGV0w6FyaWEgbm8gZWl4byBkbyB4IGUgdGF4YSBkZSBtb3J0YWxpZGFkZSBubyBlaXhvIGRvIHkKbW9ydGFsaWRhZGVfaWRhZGVfZ3JhZmljbyA8LSBnZ3Bsb3QobW9ydGFsaWRhZGVfaWRhZGUsIGFlcyh4ID0gRmFpeGFfRXRhcmlhLCB5ID0gVGF4YV9Nb3J0YWxpZGFkZSkpICsKICBnZW9tX2NvbChmaWxsID0gInNhbG1vbjEiLCB3aWR0aCA9IDAuNSwgYWVzKHRleHQgPSBwYXN0ZSggJ0ZhaXhhIEV0w6FyaWE6ICcsIEZhaXhhX0V0YXJpYSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnPGJyPlRheGEgZGUgTW9ydGFsaWRhZGUgKCUpIDonLCBUYXhhX01vcnRhbGlkYWRlKSkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLCAwKSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgbGFicyh4ID0gIiIpICsKICB0aGVtZShheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKHIgPSAyMCwgbCA9IDIwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxMiksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMiwgY29sb3IgPSAiYmxhY2siKSwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplPTEyLCBjb2xvciA9ICJibGFjayIpKQoKI1Rvcm5hciBncsOhZmljbyBpbnRlcmF0aXZvCmdncGxvdGx5KG1vcnRhbGlkYWRlX2lkYWRlX2dyYWZpY28sIHRvb2x0aXAgPSAidGV4dCIpICU+JSAKICBsYXlvdXQoeWF4aXMgPSBsaXN0KHRpdGxlID0gcGFzdGUwKGMocmVwKCImbmJzcDsiLCAyMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVGF4YSBkZSBNb3J0YWxpZGFkZSAoJSkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCImbmJzcDsiLCAyMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXAoIlxuJm5ic3A7IiwgMikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlID0gIiIpKSkKYGBgCgojIyMjIFBvciBBUlMKCjxicj4KCk5lc3RlIGdyw6FmaWNvIGRlIGJhcnJhcyBlIG1hcGEsIMOpIHBvc3PDrXZlbCB2ZXIgcXVlIGEgQVJTIExpc2JvYSBlIFZhbGUgZG8gVGVqbyDDqSBhIHF1ZSB0ZW0gYSBtYWlvciB0YXhhIGRlIG1vcnRhbGlkYWRlIHNlZ3VpZGEgZGEgQVJTIE5vcnRlLiBQb3Igb3V0cm8gbGFkbywgw6kgbm90w6F2ZWwgbyBmYWN0byBkZSBhIE1hZGVpcmEgYWluZGEgbsOjbyBhcHJlc2VudGFyIHF1YWxxdWVyIGNhc28gZGUgbW9ydGUgcGVsYSBDT1ZJRC0xOS4KCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQojQ3JpYXIgdGFiZWxhIGNvbSB1bWEgY29sdW5hIHBhcmEgYXMgUmVnacOjb2VzIGUgb3V0cmEgcGFyYSBhIG1vcnRhbGlkYWRlIG1haXMgcmVjZW50ZSBlIGRhciBub21lcyBhcHJvcHJpYWRvcwptb3J0YWxpZGFkZV9yZWdpb2VzIDwtIGRhdGEuZnJhbWUodChhcy5kYXRhLmZyYW1lKGxhcHBseShjb3ZpZDE5cHRbLCBvYml0b3NfYXJzbm9ydGU6b2JpdG9zX21hZGVpcmFdLCBsYXN0KSkgKjEwMCkgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvIHBvcHVsYWNhb19yZWdpb2VzKSAlPiUgCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJSZWdpYW8iKQpuYW1lcyhtb3J0YWxpZGFkZV9yZWdpb2VzKVsyXSA8LSAiTW9ydGFsaWRhZGUiCm1vcnRhbGlkYWRlX3JlZ2lvZXNbLCAxXSA8LSBjKCJOb3J0ZSIsICJDZW50cm8iLCAiTFZUIiwgIkFsZW50ZWpvIiwgIkFsZ2FydmUiLCAiQcOnb3JlcyIsICJNYWRlaXJhIikKCiNGYXplciBncsOhZmljbyBjb20gUmVnacOjb2VzIG5vIGVpeG8gZG8geCBlIG1vcnRhbGRpYWRlIG5vIGVpeG8gZG8geQptb3J0YWxpZGFkZV9yZWdpb2VzX2dyYWZpY28gPC0gZ2dwbG90KG1vcnRhbGlkYWRlX3JlZ2lvZXMsIGFlcyh4ID0gUmVnaWFvLCB5ID0gTW9ydGFsaWRhZGUpKSArCiAgZ2VvbV9jb2woZmlsbCA9ICJncmF5Iiwgd2lkdGggPSAwLjUsIGFlcyh0ZXh0ID0gcGFzdGUoICdBUlM6ICcsIFJlZ2lhbywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnPGJyPlRheGEgZGUgTW9ydGFsaWRhZGUgKCUpIDonLCBNb3J0YWxpZGFkZSkpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIGxhYnMoeD0iIikgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9MTIpKQptb3J0YWxpZGFkZV9yZWdpb2VzX2dyYWZpY29faW50ZXJhdGl2byA8LSBnZ3Bsb3RseShtb3J0YWxpZGFkZV9yZWdpb2VzX2dyYWZpY28sIHRvb2x0aXAgPSAidGV4dCIpICU+JSAKICBsYXlvdXQoeWF4aXMgPSBsaXN0KHRpdGxlID0gcGFzdGUwKGMocmVwKCImbmJzcDsiLCAyMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVGF4YSBkZSBNb3J0YWxpZGFkZSAoJSkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCImbmJzcDsiLCAyMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXAoIlxuJm5ic3A7IiwgMikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlID0gIiIpKSkKI21hcGEKIyNEZWZpbmlyIGludGVydmFsb3MgZGEgbGVnZW5kYQpiaW5zXzQgPSAgYygwLCAwLjAwNiwgMC4wMDEsIDAuMDE1LCAwLjAyLCAwLjAyNSwgMC4wMywgSW5mKQoKIyNPcmRlbmFyIGEgdGFiZWxhIGZlaXRhIGFudGVyaW9ybWVudGUgcGFyYSBmaWNhciBjb20gYSBtZXNtYSBvcmRlbSBxdWUgb3MgcG9saWdvbm9zIGRvIG1hcGEKbW9ydGFsaWRhZGVfcmVnaW9lc19vcmRlbSA8LSBtb3J0YWxpZGFkZV9yZWdpb2VzW2MoNCwgNSwgNiwgMiwgNywgMSwgMyksXQoKIyMjI0RlZmluaXIgYSBwYWxldGUgZGUgY29yZXMKcGFsXzQgPC0gY29sb3JCaW4oIllsT3JSZCIsIGRvbWFpbiA9IG1vcnRhbGlkYWRlX3JlZ2lvZXNfb3JkZW1bLDJdLCBiaW5zID0gYmluc180KQoKIyNEZWZpbmlyIGEgbGVnZW5kYSBxdWFuZG8gc2UgcGFzc2EgY29tIG8gcmF0byBwb3IgY2ltYQpsYWJlbHNfNCA8LSBzcHJpbnRmKAogICI8c3Ryb25nPiVzPC9zdHJvbmc+PGJyLz4lZyYjeDI1IE1vcnRhbGlkYWRlIiwKICBtb3J0YWxpZGFkZV9yZWdpb2VzX29yZGVtWywxXSwgcm91bmQobW9ydGFsaWRhZGVfcmVnaW9lc19vcmRlbVssMl0sIGRpZ2l0cyA9ICAzKQopICU+JSBsYXBwbHkoaHRtbHRvb2xzOjpIVE1MKQoKIyNGYXplciBvIG1hcAptb3J0YWxpZGFkZV9yZWdpb2VzX21hcGEgPC0gbGVhZmxldChtYXBhX3B0KSAlPiUgCiAgYWRkVGlsZXMoZ3JvdXAgPSAiTm9ybWFsIikgJT4lIAogIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJENhcnRvREIuUG9zaXRyb24sIGdyb3VwID0gIkNsYXJvIikgJT4lIAogIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJENhcnRvREIuRGFya01hdHRlck5vTGFiZWxzLCBncm91cCA9ICJFc2N1cm8iKSAlPiUgCiAgYWRkTGF5ZXJzQ29udHJvbCgKICAgIGJhc2VHcm91cHMgPSBjKCJOb3JtYWwiLCAiQ2xhcm8iLCAiRXNjdXJvIiksCiAgICBvcHRpb25zID0gbGF5ZXJzQ29udHJvbE9wdGlvbnMoY29sbGFwc2VkID0gVFJVRSkKICApICU+JSAKICBhZGRQb2x5Z29ucygKICAgIGZpbGxDb2xvciA9IH5wYWxfNChtb3J0YWxpZGFkZV9yZWdpb2VzX29yZGVtWywyXSksIAogICAgd2VpZ2h0ID0gMiwKICAgIG9wYWNpdHkgPSAxLAogICAgY29sb3IgPSAid2hpdGUiLAogICAgZGFzaEFycmF5ID0gIjMiLAogICAgZmlsbE9wYWNpdHkgPSAwLjcsCiAgICBoaWdobGlnaHQgPSBoaWdobGlnaHRPcHRpb25zKAogICAgICB3ZWlnaHQgPSA1LAogICAgICBjb2xvciA9ICIjNjY2IiwKICAgICAgZGFzaEFycmF5ID0gIiIsCiAgICAgIGZpbGxPcGFjaXR5ID0gMC43LAogICAgICBicmluZ1RvRnJvbnQgPSBUUlVFKSwKICAgIGxhYmVsID0gbGFiZWxzXzQsCiAgICBsYWJlbE9wdGlvbnMgPSBsYWJlbE9wdGlvbnMoc3R5bGUgPSBsaXN0KCJmb250LXdlaWdodCIgPSAibm9ybWFsIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZGRpbmcgPSAiM3B4IDhweCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHRzaXplID0gIjE1cHgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpcmVjdGlvbiA9ICJhdXRvIikpICU+JSAKICBhZGRMZWdlbmQocGFsID0gcGFsXzQsIHZhbHVlcyA9IG1vcnRhbGlkYWRlX3JlZ2lvZXNfb3JkZW1bLDJdLCBvcGFjaXR5ID0gMC43LCB0aXRsZSA9ICJUYXhhIGRlIE1vcnRhbGlkYWRlICglKSBwb3IgQVJTIiwKICAgICAgICAgICAgcG9zaXRpb24gPSAiYm90dG9tcmlnaHQiKQoKYnJvd3NhYmxlKAogIHRhZ0xpc3QobGlzdCgKICAgIHRhZ3MkZGl2KAogICAgICBzdHlsZSA9ICd3aWR0aDo1MCU7ZGlzcGxheTpibG9jaztmbG9hdDpsZWZ0OycsCiAgICAgIG1vcnRhbGlkYWRlX3JlZ2lvZXNfbWFwYQogICAgKSwKICAgIHRhZ3MkZGl2KAogICAgICBzdHlsZSA9ICd3aWR0aDo1MCU7ZGlzcGxheTpibG9jaztmbG9hdDpsZWZ0OycsCiAgICAgIG1vcnRhbGlkYWRlX3JlZ2lvZXNfZ3JhZmljb19pbnRlcmF0aXZvCiAgICApCiAgKSkKKQpgYGAKCgojIyMgVGF4YSBkZSBMZXRhbGlkYWRlIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LWRyb3Bkb3dufQojIyMjIFBvciBHw6luZXJvCgo8YnI+CgpDb20gYSBhbsOhbGlzZSBkZXN0ZSBncsOhZmljbyBkZSBiYXJyYXMgw6kgcG9zc8OtdmVsIGNvbmNsdWlyIHF1ZSBvcyBob21lbnMgYWZldGFkb3MgY29tIENPVklELTE5IHRlbSB1bWEgbWFpb3IgcHJvYmFiaWxpZGFkZSBkZSBtb3JyZXIsIHJlbGF0aXZhbWVudGUgw6BzIG11bGhlcmVzIGluZmV0YWRhcy4gSXN0byBwb2RlIHNlciBqdXN0aWZpY2FkbyBwZWxvIGVzdGlsbyBkZSB2aWRhIG1lbm9zIHNhdWTDoXZlbCBhZG90YWRvIHBvciBlc3RlIGfDqW5lcm8gKG1haW9yIHBlcmNlbnRhZ2VtIGRlIHRhYmFnaXNtbyBlIGFsY29vbGlzbW8pLgoKYGBge3IsIHdhcm5pbmc9RkFMU0V9CiNDw6FsY3VsbyBkYSBsZXRhbGlkYWRlIHRvdGFsLCBmZW1pbmluYSBlIG1hc2N1bGluYSBjb20gYmFzZSBubyB2YWxvciBtYWlzIHJlY2VudGUgZG9zIMOzYml0b3MsICBxdWUgw6kgdGFtYsOpbSBvIG1haXMgYWx0bywgZSBubyB2YWxvciBtYWlzIHJlY2VudGUgZGUgY29uZmlybWFkb3MKbGV0YWxpZGFkZV90b3RhbCA8LSBtYXgoY292aWQxOXB0JG9iaXRvcywgbmEucm0gPSBUUlVFKSAvIGxhc3QoY292aWQxOXB0JGNvbmZpcm1hZG9zKQpsZXRhbGlkYWRlX211bGhlcmVzIDwtIG1heChjb3ZpZDE5cHQkb2JpdG9zX2YsIG5hLnJtID0gVFJVRSkgLyBsYXN0KGNvdmlkMTlwdCRjb25maXJtYWRvc19mKQpsZXRhbGlkYWRlX2hvbWVucyA8LSBtYXgoY292aWQxOXB0JG9iaXRvc19tLCBuYS5ybSA9IFRSVUUpIC8gbGFzdChjb3ZpZDE5cHQkY29uZmlybWFkb3NfbSkKCiNDcmlhciB1bWEgdGFiZWxhIGNvbSB1bWEgY29sdW5hIHBhcmEgbyBnw6luZXJvIGUgb3V0cmEgcGFyYSBvIHZhbG9yIGRhIGxldGFsaWRhZGUgZSBkYXIgbm9tZSBhcHJvcHJpYWRvIGFvcyBnZW5lcm9zCmxldGFsaWRhZGUgPC0gZGF0YS5mcmFtZSh0KGRhdGEuZnJhbWUobGV0YWxpZGFkZV90b3RhbCwgbGV0YWxpZGFkZV9tdWxoZXJlcywgbGV0YWxpZGFkZV9ob21lbnMpKSkgJT4lIAogIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAiZ2VuZXJvIikKbmFtZXMobGV0YWxpZGFkZSlbMl0gPC0gImxldGFsaWRhZGUiCmxldGFsaWRhZGVbLCAxXSA8LSBjKCJUb3RhbCIsICJNdWxoZXJlcyIsICJIb21lbnMiKQoKI0NyaWFyIHVtIGdyw6FmaWNvIGRlIGJhcnJhcyBjb20gbyBnZW5lcm8gbm8gZWl4byBkbyB4IGUgYSBsZXRhbGlkYWRlIG5vIGVpeG8gZG8geQpnZ3Bsb3QobGV0YWxpZGFkZSwgYWVzKHggPSBnZW5lcm8sIHkgPSBsZXRhbGlkYWRlKjEwMCkpICsKICBnZW9tX2NvbChmaWxsID0gInNhbG1vbjEiLCB3aWR0aCA9IDAuNSkgKwogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsIDApKSArCiAgY29vcmRfY2FydGVzaWFuKCB5bGltID0gYygwLCBtYXgobGV0YWxpZGFkZSRsZXRhbGlkYWRlKjEwMCArIDEpKSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgbGFicyh4ID0gIiIsCiAgICAgICB5ID0gIlRheGEgZGUgTGV0YWxpZGFkZSglKSIpICsKICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKHQgPSAyMCwgYiA9IDIwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxNSksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbihyID0gMjAsIGwgPSAyMCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMTUpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMiwgY29sb3IgPSAiYmxhY2siKSkgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBzY2FsZXM6OnBlcmNlbnQobGV0YWxpZGFkZSwgZGlnaXRzID0gNCkpLCAKICAgICAgICAgICAgdmp1c3QgPSAtMC41LCAKICAgICAgICAgICAgc2l6ZSA9IDQpCmBgYAoKCiMjIyMgRXZvbHXDp8OjbyBwb3IgR8OpbmVybwoKPGJyPgoKTm8gZ3LDoWZpY28gZGUgbGluaGFzIHBvZGVtb3MgdmVyIHF1ZSwgYSBwYXJ0aXIgZGUgbWVhZG9zIGRlIG1hcsOnbywgYSBsZXRhbGlkYWRlIHNvZnJldSB1bSBhdW1lbnRvIGNvbnNpZGVyw6F2ZWwgdW1hIHZleiBxdWUgb3MgbWFpcyB2ZWxob3MsIHBvcHVsYcOnw6NvIG1haXMgZGViaWxpdGFkYSwgZXJhbSBkb3MgZ3J1cG9zIGV0w6FyaW9zIG1haXMgYWZldGFkb3MsIGF0aW5naW5kbyBvIHNldSBwaWNvIG5vIGRpYSAwNS8wNS8yMDIwIGNvbSA1LjA0JS4gQSBwYXJ0aXIgZGUganVuaG8sIGEgbGV0YWxpZGFkZSB0ZW0gdmluZG8gYSBkaW1pbnVpci4gVW1hIGRhcyByYXrDtWVzIHF1ZSBwb2RlIGV4cGxpY2FyIGVzdGUgZmFjdG8gw6kgYSBmYWl4YSBldMOhcmlhIGRhIHBvcHVsYcOnw6NvIGluZmV0YWRhLCBxdWUgc2UgYWx0ZXJvdSwgcGFzc2FuZG8gZG9zIG1haXMgdmVsaG9zIHBhcmEgb3MgbWFpcyBqb3ZlbnMsIHF1ZSB0w6ptIG1lbm9yIHByb2JhYmlsaWRhZGUgZGUgbW9ycmVyIGRhIGRvZW7Dp2EgdmlyYWwuIFBhcmEgYWzDqW0gZGVzdGUgbW90aXZvLCBleGlzdGVtIGFpbmRhIG91dHJvcyBmYXRvcmVzIGEgY29uc2lkZXJhciwgbm9tZWFkYW1lbnRlIHVtIG1haW9yIGNvbmhlY2ltZW50byBlIGV4cGVyacOqbmNpYSBwb3IgcGFydGUgZG9zIHByb2Zpc3Npb25haXMgZGUgc2HDumRlLCB1bSBhbGFyZ2FtZW50byBkbyBuw7ptZXJvIGRlIHRlc3RlcyByZWFsaXphZG9zIGUgYWluZGEgdW1hIG1lbGhvcmlhIGRhIGNhcGFjaWRhZGUgZGUgcmVzcG9zdGEgZG8gc2lzdGVtYSBkZSBzYcO6ZGUuCgpgYGB7ciwgd2FybmluZz1GQUxTRX0KI0NhbGN1bGFyIGxldGFsaWRhZGUgdG9hbCwgcGFyYSBtdWxoZXJlcyBlIHBhcmEgaG9tZW5zLCBjcmlhbmRvIHVtYSB0YWJlbGEgcGFyYSBjYWRhIGNvbSB1bWEgY29sdW5hIHBhcmEgYSAgZGF0YSBlIG91dHJhIHBhcmEgb3MgdmFsb3JlcyBkYSBsZXRhbGlkYWRlIHBhcmEgY2FkYSBkaWEKbGV0YWxpZGFkZV90ZW1wb190b3RhbCA8LSBjYmluZChjb3ZpZDE5cHQkZGF0YSwgYXMuZGF0YS5mcmFtZSgoY292aWQxOXB0JG9iaXRvcyAvIGNvdmlkMTlwdCRjb25maXJtYWRvcykqMTAwKSkKbGV0YWxpZGFkZV90ZW1wb19tdWxoZXJlcyA8LSBjYmluZChjb3ZpZDE5cHQkZGF0YSwgYXMuZGF0YS5mcmFtZSgoY292aWQxOXB0JG9iaXRvc19mIC8gY292aWQxOXB0JGNvbmZpcm1hZG9zX2YpKjEwMCkpCmxldGFsaWRhZGVfdGVtcG9faG9tZW5zIDwtIGNiaW5kKGNvdmlkMTlwdCRkYXRhLCBhcy5kYXRhLmZyYW1lKChjb3ZpZDE5cHQkb2JpdG9zX20gLyBjb3ZpZDE5cHQkY29uZmlybWFkb3NfbSkqMTAwKSkKCiNKdW50YXIgYXMgMyB0YWJlbGFzIG51bWEgc8OjbyBtdWRhbmRvIG9zIG5vbWVzIGRlIGNhZGEgY29sdW5hCmxldGFsaWRhZGVfdGVtcG9fdG90YWxfbXVsaGVyZXMgPC0gbWVyZ2UobGV0YWxpZGFkZV90ZW1wb190b3RhbCwgbGV0YWxpZGFkZV90ZW1wb19tdWxoZXJlcywgYnkgPSJjb3ZpZDE5cHQkZGF0YSIpCmxldGFsaWRhZGVfdGVtcG8gPC0gbWVyZ2UobGV0YWxpZGFkZV90ZW1wb190b3RhbF9tdWxoZXJlcywgbGV0YWxpZGFkZV90ZW1wb19ob21lbnMsIGJ5PSJjb3ZpZDE5cHQkZGF0YSIpCm5hbWVzKGxldGFsaWRhZGVfdGVtcG8pIDwtIGMoIkRhdGEiLCAiVG90YWwiLCAiRmVtaW5pbm8iLCAiTWFzY3VsaW5vIikKCiNGYXplciBvIG1lbHQgcGFyYSBwb2RlciBmYXplIHVtIGdyw6FmaWNvIGRlIGxpbmhhcwpsZXRhbGlkYWRlX3RlbXBvX21lbHQgPC0gbWVsdChsZXRhbGlkYWRlX3RlbXBvLCBpZC52YXJzID0gIkRhdGEiKQpuYW1lcyhsZXRhbGlkYWRlX3RlbXBvX21lbHQpIDwtIGMoIkRhdGEiLCAiR2VuZXJvIiwgIkxldGFsaWRhZGUiKQoKI0ZhemVyIGdyw6FmaWNvIGRlIGxpbmhhcyBjb20gYSBkYXRhIG5vIGVpeG8gZG8geCwgYSBsZXRhbGlkYWRlIG5vIGVpeG8gZG8geSBlIG8gZ8OpbmVybyBlbSBjYWRhIGxpbmhhCmxldGFsaWRhZGVfdGVtcG9fZ3JhZmljbyA8LSBnZ3Bsb3QobGV0YWxpZGFkZV90ZW1wb19tZWx0LCBhZXMoeCA9IERhdGEsIHkgPSBMZXRhbGlkYWRlLCBjb2xvciA9IEdlbmVybykpICsKICBnZW9tX2xpbmUoc2l6ZT0wLjUpICsKICBnZW9tX3BvaW50KHNpemU9MC4xLCBhZXModGV4dCA9IHBhc3RlKCAnRGF0YTogJywgRGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnPGJyPkfDqW5lcm8gOicsIEdlbmVybywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnPGJyPlRheGEgZGUgTGV0YWxpZGFkZSAoJSkgOicsIExldGFsaWRhZGUgKSkpICsKICBsYWJzKHggPSAiIiwKICAgICAgIHkgPSAiVGF4YSBkZSBMZXRhbGlkYWRlICglKSIpICsKICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMikpKwogIHNjYWxlX3hfZGF0ZShicmVha3MgPSAiMyBtb250aHMiLCBkYXRlX2xhYmVscyA9ICIlYiAlZCIpCgojVG9ybmFyIGdyw6FmaWNvIGludGVyYXRpdm8KZ2dwbG90bHkobGV0YWxpZGFkZV90ZW1wb19ncmFmaWNvLCBhZGRfdHJhY2V5ID0gIlRheGEgZGUgTGV0YWxpZGFkZSAoJSkiLCB0b29sdGlwID0gInRleHQiKSAlPiUgCiAgbGF5b3V0KGxlZ2VuZCA9IGxpc3QoeCA9IDEsIHkgPSAwKSkKYGBgCgoKIyMjIyBQb3IgRmFpeGEgRXTDoXJpYSBlIEfDqW5lcm8KCjxicj4KClBlbGEgYW7DoWxpc2UgZG8gZ3LDoWZpY28gZGUgcG9udG9zLCDDqSBwb3Nzw612ZWwgdmVyIHF1ZSBhcyBmYWl4YXMgZXTDoXJpYXMgZW50cmUgb3MgMCBlIG9zIDQ5IGFub3MgbsOjbyBhcHJlc2VudGFtIGRpZmVyZW7Dp2FzIHNpZ25pZmljYXRpdmFzIG5vcyB2YWxvcmVzIGRhIGxldGFsaWRhZGUgZW50cmUgc2ksIGUgbyBtZXNtbyBhY29udGVjZSBwYXJhIG9zIGfDqW5lcm9zIGRlbnRybyBkZSBjYWRhIGZhaXhhIGV0w6FyaWEuCgpPcyBob21lbnMgdGVuZGVtIGEgYXByZXNlbnRhciB1bWEgdGF4YSBkZSBsZXRhbGlkYWRlIHN1cGVyaW9yIGEgcGFydGlyIGRhIGZhaXhhIGV0w6FyaWEgZG9zIDUwIGFvcyA1OSBhbm9zLCBxdWUgc2UgdmFpIGFjZW50dWFuZG8gY29tIGEgaWRhZGUsIG8gcXVlLCBkZSBhY29yZG8gY29tIGVzdHVkb3MgcmVjZW50ZXMsIHBvZGUgZXN0YXIgcmVsYWNpb25hZG8gY29tIGEgcHLDqS1leGlzdMOqbmNpYSBkZSBtYWlvciBuw7ptZXJvIGRlIGNvLW1vcmJpbGlkYWRlcywgY29tIHVtIG1haW9yIGNvbnN1bW8gZGUgYmViaWRhcyBhbGNvw7NsaWNhcyBlIG1haW9yIHRlbmTDqm5jaWEgcGFyYSBvIHRhYmFnaXNtbywgZGlmZXJlbsOnYXMgbmEgcmVzcG9zdGEgaW11bml0w6FyaWEsIHF1ZXN0w7VlcyBmaXNpb2zDs2dpY2FzIHJlbGFjaW9uYWRhcyBjb20gbyByZWNldG9yIEFDRTIgdmlyYWwgKHF1ZSBwb2RlIHRlciB1bWEgZXhwcmVzc8OjbyBkaWZlcmVudGUgZW50cmUgZ8OpbmVyb3MpIGUsIGFpbmRhLCBkaWZlcmVuw6dhcyBjb21wb3J0YW1lbnRhaXMsIG5vbWVhZGFtZW50ZSB1bWEgbWVub3IgdGVuZMOqbmNpYSBwYXJhIHJlY29ycmVyIGEgc2VydmnDp29zIG3DqWRpY29zLgoKw4kgYWluZGEgcmVsZXZhbnRlIG1lbmNpb25hciBxdWUgYSB0YXhhIGRlIGxldGFsaWRhZGUgYXVtZW50YSBjb20gbyBhdW1lbnRvIGRhIGlkYWRlLiBQb2RlIGRldmVyLXNlIGFvIGZhY3RvIGRlIHNlcmVtIGZhaXhhcyBldMOhcmlhcyBtYWlzIGRlYmlsaXRhZGFzIGUsIG5vcm1hbG1lbnRlLCBjb20gbWFpb3IgbsO6bWVybyBkZSBkb2Vuw6dhcyBjb25jb21pdGFudGVzLiBJc3RvIMOpIHBhcnRpY3VsYXJtZW50ZSBub3TDs3JpbyBuYSBmYWl4YSBldMOhcmlhIGRvcyA4MCsuCgpgYGB7ciwgd2FybmluZz1GQUxTRX0KI0NyaWFyIHRhYmVsYSBjb20gdW1hIGNvbHVuZGEgcGFyYSBhIGZhaXhhIGV0w6FyaWEgZSBvdXRyYSBwYXJhIG8gbsO6bWVybyBkZSBjYXNvcyB0b3RhbCBlIG11ZGFyIGNvbHVuYSBkYSBmYWl4YSBldMOhcmlhIHBhcmEgb3Mgbm9tZXMgYWRlcXVhZG9zCmNhc29zX3RvdGFsX2lkYWRlX2ludmVydGlkbyA8LSBhcy5kYXRhLmZyYW1lKHQoY2Fzb3NfdG90YWxfaWRhZGUpKSAlPiUgCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJJZGFkZSIpCm5hbWVzKGNhc29zX3RvdGFsX2lkYWRlX2ludmVydGlkbylbMl0gPC0gIlRvdGFsIgpjYXNvc190b3RhbF9pZGFkZV9pbnZlcnRpZG9bLDFdIDwtIGMoIjAtOSIsICIxMC0xOSIsICIyMC0yOSIsICIzMC0zOSIsICI0MC00OSIsICI1MC01OSIsICI2MC02OSIsICI3MC03OSIsICI4MCsiKQoKI1RhYmVsYSBjb20gbsO6bWVybyBkZSBjYXNvcyBjb25maXJtYWRvcyBwb3IgZmFpeGEgZXTDoXJpYSBwb3IgZ8OpbmVybwpjYXNvc19nZW5lcm9faWRhZGUgPC0gbWVyZ2UoY2Fzb3NfZmVtaW5pbm9zX2lkYWRlX2ludmVydGlkbywgY2Fzb3NfbWFzY3VsaW5vc19pZGFkZV9pbnZlcnRpZG8sIGJ5ID0gIklkYWRlIikKY2Fzb3NfZ2VuZXJvX2lkYWRlX3RvdGFsIDwtICBtZXJnZShjYXNvc19nZW5lcm9faWRhZGUsIGNhc29zX3RvdGFsX2lkYWRlX2ludmVydGlkbywgYnkgPSAiSWRhZGUiKQoKI1NvbWFyIGEgdGFiZWxhIGRvcyBmZW1pbmlub3MgY29tIGEgZG9zIG1hc2N1bGlub3MgbyBxdWUgdmFpIGRhciBvIG7Dum1lcm8gZGUgw7NiaXRvcyBhdMOpIGFvIG1vbWVudG8gcG9yIGlkYWRlIGFwZW5hcwptb3J0ZXNfdG90YWxfaWRhZGUgPC0gYXMuZGF0YS5mcmFtZShtb3J0ZXNfZmVtaW5pbm9zX2lkYWRlICsgbW9ydGVzX21hc2N1bGlub3NfaWRhZGUpCgojQ3JpYXIgdGFiZWxhIGNvbSB1bWEgY29sdW5kYSBwYXJhIGEgZmFpeGEgZXTDoXJpYSBlIG91dHJhIHBhcmEgbyBuw7ptZXJvIGRlIMOzYml0b3MgdG90YWwgZSBtdWRhciBjb2x1bmEgZGEgZmFpeGEgZXTDoXJpYSBwYXJhIG9zIG5vbWVzIGFkZXF1YWRvcwptb3J0ZXNfdG90YWxfaWRhZGVfaW52ZXJ0aWRvIDwtIGFzLmRhdGEuZnJhbWUodChtb3J0ZXNfdG90YWxfaWRhZGUpKSAlPiUgCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJJZGFkZSIpCm5hbWVzKG1vcnRlc190b3RhbF9pZGFkZV9pbnZlcnRpZG8pWzJdIDwtICJUb3RhbCIKbW9ydGVzX3RvdGFsX2lkYWRlX2ludmVydGlkb1ssMV0gPC0gYygiMC05IiwgIjEwLTE5IiwgIjIwLTI5IiwgIjMwLTM5IiwgIjQwLTQ5IiwgIjUwLTU5IiwgIjYwLTY5IiwgIjcwLTc5IiwgIjgwKyIpCgojVGFiZWxhIGNvbSBuw7ptZXJvIGRlIMOzYml0b3MgcG9yIGZhaXhhIGV0w6FyaWEgcG9yIGfDqW5lcm8KbW9ydGVzX2dlbmVyb19pZGFkZSA8LSBtZXJnZShtb3J0ZXNfZmVtaW5pbm9zX2lkYWRlX2ludmVydGlkbywgbW9ydGVzX21hc2N1bGlub3NfaWRhZGVfaW52ZXJ0aWRvLCBieSA9ICJJZGFkZSIpCm1vcnRlc19nZW5lcm9faWRhZGVfdG90YWwgPC0gIG1lcmdlKG1vcnRlc19nZW5lcm9faWRhZGUsIG1vcnRlc190b3RhbF9pZGFkZV9pbnZlcnRpZG8sIGJ5ID0gIklkYWRlIikKCiNDcmlhciB0YWJlbGEgY29tIHVtYSBjb2x1bmEgY29tIGFzIGZhaXhhcyBldMOhcmlvYXMgZSBvdXRyYSBjb20gYSBsZXRhbGlkYWRlIGUgZGFyIG5vbWVzIMOgcyBjb2x1bmFzCmxldGFsaWRhZGVfZ2VuZXJvX2lkYWRlIDwtIGNiaW5kKGNhc29zX2ZlbWluaW5vc19pZGFkZV9pbnZlcnRpZG9bLDFdLCAobW9ydGVzX2dlbmVyb19pZGFkZV90b3RhbFssMjo0XS9jYXNvc19nZW5lcm9faWRhZGVfdG90YWxbLDI6NF0pKQpuYW1lcyhsZXRhbGlkYWRlX2dlbmVyb19pZGFkZSkgPC0gYygiSWRhZGUiLCAiRmVtaW5pbm8iLCAiTWFzY3VsaW5vIiwgIlRvdGFsIikKCiNGYXplciBtZWx0IHBhcmEgcG9kZXIgZmF6ZXIgZ3LDoWZpY28KbGV0YWxpZGFkZV9nZW5lcm9faWRhZGVfbWVsdCA8LSBtZWx0KGxldGFsaWRhZGVfZ2VuZXJvX2lkYWRlLCBpZC52YXJzID0gIklkYWRlIikKCiNGYXplciBncsOhZmljbyBjb20gaWRhZGUgbm8gZWl4byBkbyB4LCBsZXRhbGlkYWRlIG5vIGVpeG8gZG8geSBlIGZhaXhhIGV0w6FyaWEgZW0gY2FkYSBsaW5oYQpsZXRhbGlkYWRlX2dlbmVyb19pZGFkZV9ncmFmaWNvIDwtIGdncGxvdChsZXRhbGlkYWRlX2dlbmVyb19pZGFkZV9tZWx0LCBhZXMoeCA9IElkYWRlLCB5ID0gdmFsdWUqMTAwLCBjb2xvciA9IHZhcmlhYmxlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvb2x0aXAgPSByb3VuZCh2YWx1ZSoxMDAsIGRpZ2l0cyA9IDIpLCBkYXRhX2lkID0gdmFsdWUpKSArCiAgZ2VvbV9wb2ludF9pbnRlcmFjdGl2ZSgpICsKICBsYWJzKHggPSIiLAogICAgICAgeSA9ICJUYXhhIGRlIExldGFsaWRhZGUgKCUpIikgKwogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4odCA9IDIwLCBiID0gMjAsKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxMiksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbihyID0gMjAsIGwgPSAyMCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMTIpKSArCiAgc2NhbGVfY29sb3JfZGlzY3JldGUobmFtZT0gIkdlbsOpcm8iKQogICAgICAgIAojQW5pbWFyIG8gZ3LDoWZpY28gCmdpcmFmZShjb2RlID0gcHJpbnQobGV0YWxpZGFkZV9nZW5lcm9faWRhZGVfZ3JhZmljbyksCiAgICAgICBvcHRpb25zID0gbGlzdCgKICAgICAgICAgb3B0c196b29tKG1heCA9IDIpLAogICAgICAgICBvcHRzX2hvdmVyKGNzcyA9ICJmaWxsOmJsYWNrOyIpLAogICAgICAgICBvcHRzX3NpemluZyhyZXNjYWxlID0gVFJVRSwgd2lkdGggPSAwLjgpCiAgICAgICApKQpgYGAKCgojIyMjIEV2b2x1w6fDo28gcG9yIEZhaXhhIEV0w6FyaWEKCjxicj4KCk5lc3RlIGdyw6FmaWNvIGRlIGxpbmhhcyBwb2RlbW9zIHZlcmlmaWNhciBxdWUgbmFzIGZhaXhhcyBldMOhcmlhcyBlbnRyZSBvcyAwIGUgb3MgNTkgYW5vcywgYSB0YXhhIGRlIGxldGFsaWRhZGUgdGVtLXNlIG1hbnRpZG8gcmVsYXRpdmFtZW50ZSBjb25zdGFudGUgZSBiYWl4YSwgdW1hIHZleiBxdWUgbsOjbyBjb25zdGl0dWVtIGEgZnJhw6fDo28gZGEgcG9wdWxhw6fDo28gZGUgbWFpb3IgcmlzY28uCgpSZWxhdGl2YW1lbnRlIMOgcyBmYWl4YXMgZXTDoXJpYXMgZW50cmUgb3MgNjAgZSBvcyA4MCsgKGZhaXhhcyBldMOhcmlhcyBkZSByaXNjbyksIGEgdGF4YSBkZSBsZXRhbGlkYWRlIGZvaSBhdW1lbnRhbmRvIHByb2dyZXNzaXZhbWVudGUgYXTDqSBqdW5obyBkYWRhIGEgZmFsdGEgZGUgY29uaGVjaW1lbnRvIGluaWNpYWwgZGVzdGEgZG9lbsOnYSB2aXJhbCBlIGEgb2NvcnLDqm5jaWEgZGUgc3VydG9zIGVtIGxhcmVzLiBQb3N0ZXJpb3JtZW50ZSwgYXMgdGF4YXMgZGUgbGV0YWxpZGFkZSB0w6ptIHZpbmRvIGEgZGltaW51aXIgcG9pcywgcGFyYSBhbMOpbSBkZSB1bSBtYWlvciBjb25oZWNpbWVudG8sIGV4aXN0ZSB1bWEgbWVsaG9yIGNhcGFjaWRhZGUgZGUgcmVzcG9zdGEgbcOpZGljYS4gTm8gZW50YW50bywgcHJldmVtb3MgdW0gYXVtZW50byBkZXN0YXMgdGF4YXMgZGV2aWRvIGFvIHJlY2VudGUgYXVtZW50byBubyBuw7ptZXJvIGRlIGNhc29zIG5lc3RhcyBmYWl4YXMgZXTDoXJpYXMuCgpgYGB7ciwgd2FybmluZz1GQUxTRX0KI1RhYmVsYSBjb20gbyBuw7ptZXJvIGRlIG1vcnRlcyB0b3RhbCBkacOhcmlvcyBwb3IgZmFpeGEgZXTDoXJpYQp0b3RhbF9tb3J0ZXNfbm92b3MgPC0gZmVtaW5pbm9zX21vcnRlcyArIG1hc2N1bGlub3NfbW9ydGVzCgojVGFiZWxhIGNvbSBvIG7Dum1lcm8gZGUgY2Fzb3MgdG90YWlzIGRpw6FyaW9zIHBvciBmYWl4YSBldMOhcmlhCnRvdGFsX2Nhc29zX25vdm9zIDwtIGZlbWluaW5vcyArIG1hc2N1bGlub3MKCiNUYWJlbGEgY29tIHVtYSBjb2x1bmEgY29tIGEgZGF0YSBlIG91dHJhcyBjb20gY2FkYSBmYWl4YSBldMOhcmlhIG9uZGUgdGVtIG8gdmFsb3IgZGEgbGV0YWxpZGFkZSB0b3RhbCBwYXJhIGNhZGEgZGlhIGUgIGRhciBub21lcyDDoHMgY29sdW5hcwpsZXRhbGlkYWRlX3RlbXBvX2lkYWRlIDwtIGNiaW5kKGNvdmlkMTlwdCRkYXRhLCB0b3RhbF9tb3J0ZXNfbm92b3MvdG90YWxfY2Fzb3Nfbm92b3MpCm5hbWVzKGxldGFsaWRhZGVfdGVtcG9faWRhZGUpIDwtIGMoIkRhdGEiLCAiMC05IiwgIjEwLTE5IiwgIjIwLTI5IiwgIjMwLTM5IiwgIjQwLTQ5IiwgIjUwLTU5IiwgIjYwLTY5IiwgIjcwLTc5IiwgIjgwKyIpCgojRmF6ZXIgbWVsdCBwYXJhIGZhemVyIG8gZ3LDoWZpY28KbGV0YWxpZGFkZV90ZW1wb19pZGFkZV9tZWx0IDwtIG1lbHQobGV0YWxpZGFkZV90ZW1wb19pZGFkZSwgaWQudmFycyA9ICJEYXRhIikKCiNGYXplciBvIGdyw6FmaWNvCmxldGFsaWRhZGVfdGVtcG9faWRhZGVfZ3JhZmljbyA8LSBnZ3Bsb3QobGV0YWxpZGFkZV90ZW1wb19pZGFkZV9tZWx0LCBhZXMoeCA9IERhdGEsIHkgPSB2YWx1ZSoxMDAsIGNvbG9yID0gdmFyaWFibGUpKSArCiAgZ2VvbV9saW5lKHNpemUgPSAwLjUpICsKICBnZW9tX3BvaW50KHNpemU9MC4xLCBhZXModGV4dCA9IHBhc3RlKCAnRGF0YTogJywgRGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnPGJyPkZhaXhhIEV0w6FyaWEgOicsIHZhcmlhYmxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+VGF4YSBkZSBMZXRhbGlkYWRlICglKSA6JywgdmFsdWUqMTAwICkpKSArCiAgbGFicyh4ID0iIiwKICAgICAgIHkgPSAiVGF4YSBkZSBMZXRhbGlkYWRlICglKSIpICsKICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQobWFyZ2luID0gbWFyZ2luKHQgPSAyMCAsYiA9IDIwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxNSksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbihyID0gMjAsIGwgPSAyMCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMTUpLAogICAgICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDApLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHNjYWxlX3hfZGF0ZShicmVha3MgPSAiMyBtb250aHMiLCBkYXRlX2xhYmVscyA9ICIlYiAlZCIpCgojVG9ybmFyIG8gZ3LDoWZpY28gaW50ZXJhdGl2bwpnZ3Bsb3RseShsZXRhbGlkYWRlX3RlbXBvX2lkYWRlX2dyYWZpY28sIHRvb2x0aXAgPSAidGV4dCIpCgpgYGAKCgojIyMjIFBvciBBUlMKCjxicj4KCkFvIGludGVycHJldGFybW9zIGVzdGUgZ3LDoWZpY28gZGUgYmFycmFzIGUgZXN0ZSBtYXBhLCB2ZXJpZmljYW1vcyBxdWUgb3MgQcOnb3JlcyB0w6ptIHVtYSB0YXhhIGRlIGxldGFsaWRhZGUgbXVpdG8gZWxldmFkYSBvIHF1ZSBwb2RlIGRldmVyLXNlIGEgdW1hIGTDqWJpbCBlc3RydXR1cmEgbcOpZGljYSBlL291IHVtYSBtYWlvciBpbmNpZMOqbmNpYSBuYSBwb3B1bGHDp8OjbyBtYWlzIGVudmVsaGVjaWRhLiBPIG1lc21vIHRhbWLDqW0gc2UgdmVyaWZpY2EgbmEgQVJTIGRvIENlbnRybywgYWluZGEgcXVlIGNvbSB1bWEgdGF4YSBkZSBsZXRhbGlkYWRlIGxpZ2VpcmFtZW50ZSBtZW5vciwgcXVlLCDDoHMgcmF6w7VlcyBhbnRlcmlvcm1lbnRlIG1lbmNpb25hZGFzLCBwb2RlLXNlIGFjcmVzY2VudGFyIG8gZmFjdG8gZGUgZXhpc3RpciB1bWEgZWxldmFkYSBkaXNjcmVww6JuY2lhIGRlIGFjZXNzaWJpbGlkYWRlIGFvcyBzZXJ2acOnb3MgaG9zcGl0YWxhcmVzIGVudHJlIG9zIGNvbmNlbGhvcyBkbyBsaXRvcmFsIGUgZG8gaW50ZXJpb3IuCgpSZWxhdGl2YW1lbnRlIMOgIEFSUyBkbyBOb3J0ZSwgZXN0YSBhcHJlc2VudGEgYSB0ZXJjZWlyYSB0YXhhIGRlIGxldGFsaWRhZGUgbWFpcyBlbGV2YWRhLCBwcm92YXZlbG1lbnRlIHJlc3VsdGFudGUgZG9zIHByaW1laXJvcyBzdXJ0b3MgZW0gUG9ydHVnYWwgdGVyZW0gb2NvcnJpZG8gbmVzdGEgQVJTLiAKCk5hcyBBUlNzIGRvIEFsZ2FydmUgZSBkbyBBbGVudGVqbywgZXJhIGRlIGVzcGVyYXIgcXVlIGFzIHRheGFzIGRlIGxldGFsaWRhZGUgZm9zc2VtIG1haXMgZWxldmFkYXMuIE5vIGVudGFudG8gaXN0byBuw6NvIHNlIHZlcmlmaWNhLCBwb3NzaXZlbG1lbnRlIHBlbG8gZmFjdG8gZGUgdGVyZW0gc2lkbyBhdGluZ2lkYXMgZmFpeGFzIGV0w6FyaWFzIG1haXMgam92ZW5zIHF1ZSBlc3RhYmVsZWNlbSBtYWlzIGNvbnRhY3RvIGVudHJlIHNpLCBlbnF1YW50byBxdWUgYXMgZmFpeGFzIGV0w6FyaWFzIG1haXMgdmVsaGFzIHNlIGVuY29udHJhbSBlbSB6b25hcyBydXJhaXMgZSwgcG9yIGlzc28sIG1haXMgaXNvbGFkYXMuCgpBIHRheGEgZGUgbGV0YWxpZGFkZSBuYSBBUlMgZGUgTGlzYm9hIGUgVmFsZSBkbyBUZWpvIHBhcmVjZSBzZXIgYmFpeGEgZGFkYSBhIHByZXZhbMOqbmNpYSBxdWUgZXhpc3RlIG5lc3RhIEFSUy4gSXN0byBkZW1vbnN0cmEgcXVlIHBvc3N1aSB1bSBzZXJ2acOnbyBkZSBzYcO6ZGUgZWZpY2F6IGNvbSB1bWEgYm9hIHJlc3Bvc3RhIG3DqWRpY2EuCgpOYSBNYWRlaXJhIGEgdGF4YSBkZSBsZXRhbGlkYWRlIMOpIHplcm8sIHVtYSB2ZXogcXVlIG7Do28gc2UgdmVyaWZpY2FyYW0gw7NiaXRvcyBuZXN0YSByZWdpw6NvLiBFc3RlIHZhbG9yIHBvZGUgZGV2ZXItc2UsIHBvciB1bSBsYWRvIMOgIHF1YWxpZGFkZSBkbyBzZXJ2acOnbyBtw6lkaWNvIHByZXN0YWRvIG91LCBwb3Igb3V0cm8gbGFkbywgYSB1bWEgbWVub3IgaW5jaWTDqm5jaWEgbmFzIGZhaXhhcyBldMOhcmlhcyBjb20gbWFpb3IgcmlzY28gZGUgbW9ydGUuCgpgYGB7ciwgd2FybmluZz1GQUxTRX0KI0ZhemVyIHVtYSB0YWJlbGEgY29tIHVtYSBjb2x1bmEgY29tIGEgUmVnacOjbyBlIG91dHJhIGNvbSBhIGxldGFsaWRhZGUgcGFyYSBjYWRhIFJlZ2nDo28gZSBkYXIgbm9tZXMgYWRlcXVhZG9zCmxldGFsaWRhZGVfcmVnaW9lcyA8LSBkYXRhLmZyYW1lKHQoYXMuZGF0YS5mcmFtZShsYXBwbHkoY292aWQxOXB0Wywgb2JpdG9zX2Fyc25vcnRlOm9iaXRvc19tYWRlaXJhXSwgbGFzdCkpKjEwMCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvIChhcy5kYXRhLmZyYW1lKGxhcHBseShjb3ZpZDE5cHRbLCBjb25maXJtYWRvc19hcnNub3J0ZTpjb25maXJtYWRvc19tYWRlaXJhXSwgbGFzdCkpKSkpICU+JSAKICByb3duYW1lc190b19jb2x1bW4odmFyID0gIlJlZ2lhbyIpCm5hbWVzKGxldGFsaWRhZGVfcmVnaW9lcylbMl0gPC0gIkxldGFsaWRhZGUiCmxldGFsaWRhZGVfcmVnaW9lc1ssIDFdIDwtIGMoIk5vcnRlIiwgIkNlbnRybyIsICJMVlQiLCAiQWxlbnRlam8iLCAiQWxnYXJ2ZSIsICJBw6dvcmVzIiwgIk1hZGVpcmEiKQoKI0ZhemVyIG8gZ3LDoWZpY28gY29tIGEgUmVnacOjbyBubyBlaXhvIGRvIHggZSBhIGxldGFsaWRhZGUgbm8gZWl4byBkbyB5CmxldGFsaWRhZGVfcmVnaW9lc19ncmFmaWNvIDwtIGdncGxvdChsZXRhbGlkYWRlX3JlZ2lvZXMsIGFlcyh4ID0gUmVnaWFvLCB5ID0gTGV0YWxpZGFkZSkpICsKICBnZW9tX2NvbChmaWxsID0gImdyYXkiLCB3aWR0aCA9IDAuNSwgYWVzKHRleHQgPSBwYXN0ZSggJ0FSUzogJywgUmVnaWFvLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+VGF4YSBkZSBMZXRhbGlkYWRlICglKSA6JywgTGV0YWxpZGFkZSkpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCkpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIGxhYnMoeCA9ICIiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMikpCgpsZXRhbGlkYWRlX3JlZ2lvZXNfZ3JhZmljb19pbnRlcmF0aXZvIDwtIGdncGxvdGx5KGxldGFsaWRhZGVfcmVnaW9lc19ncmFmaWNvLCB0b29sdGlwID0gInRleHQiKSAlPiUgCiAgbGF5b3V0KHlheGlzID0gbGlzdCh0aXRsZSA9IHBhc3RlMChjKHJlcCgiJm5ic3A7IiwgMjApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRheGEgZGUgTGV0YWxpZGFkZSAoJSkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCImbmJzcDsiLCAyMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXAoIlxuJm5ic3A7IiwgMikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlID0gIiIpKSkKI21hcGEKIyNEZWZpbmlyIGludGVydmFsb3MgZGEgbGVnZW5kYQpiaW5zXzUgPSAgYygwLCAxLCAyLCAzLCA0LCA1LCBJbmYpCgojI09yZGVuYXIgYSB0YWJlbGEgZmVpdGEgYW50ZXJpb3JtZW50ZSBwYXJhIGZpY2FyIGNvbSBhIG1lc21hIG9yZGVtIHF1ZSBvcyBwb2xpZ29ub3MgZG8gbWFwYQpsZXRhbGlkYWRlX3JlZ2lvZXNfb3JkZW0gPC0gbGV0YWxpZGFkZV9yZWdpb2VzW2MoNCwgNSwgNiwgMiwgNywgMSwgMyksXQoKIyNEZWZpbmlyIGEgcGFsZXRlIGRlIGNvcmVzCnBhbF81IDwtIGNvbG9yQmluKCJZbE9yUmQiLCBkb21haW4gPSBsZXRhbGlkYWRlX3JlZ2lvZXNfb3JkZW1bLDJdLCBiaW5zID0gYmluc181KQoKIyNEZWZpbmlyIGEgbGVnZW5kYSBxdWFuZG8gc2UgcGFzc2EgY29tIG8gcmF0byBwb3IgY2ltYQpsYWJlbHNfNSA8LSBzcHJpbnRmKAogICI8c3Ryb25nPiVzPC9zdHJvbmc+PGJyLz4lZyYjeDI1IExldGFsaWRhZGUiLAogIGxldGFsaWRhZGVfcmVnaW9lc19vcmRlbVssMV0sIHJvdW5kKGxldGFsaWRhZGVfcmVnaW9lc19vcmRlbVssMl0sIGRpZ2l0cyA9ICAyKQopICU+JSBsYXBwbHkoaHRtbHRvb2xzOjpIVE1MKQoKIyNGYXplciBvIG1hcGEKbGV0YWxpZGFkZV9yZWdpb2VzX21hcGEgPC0gbGVhZmxldChtYXBhX3B0KSAlPiUgCiAgYWRkVGlsZXMoZ3JvdXAgPSAiTm9ybWFsIikgJT4lIAogIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJENhcnRvREIuUG9zaXRyb24sIGdyb3VwID0gIkNsYXJvIikgJT4lIAogIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJENhcnRvREIuRGFya01hdHRlck5vTGFiZWxzLCBncm91cCA9ICJFc2N1cm8iKSAlPiUgCiAgYWRkTGF5ZXJzQ29udHJvbCgKICAgIGJhc2VHcm91cHMgPSBjKCJOb3JtYWwiLCAiQ2xhcm8iLCAiRXNjdXJvIiksCiAgICBvcHRpb25zID0gbGF5ZXJzQ29udHJvbE9wdGlvbnMoY29sbGFwc2VkID0gVFJVRSkKICApICU+JSAKICBhZGRQb2x5Z29ucygKICAgIGZpbGxDb2xvciA9IH5wYWxfNShsZXRhbGlkYWRlX3JlZ2lvZXNfb3JkZW1bLDJdKSwgCiAgICB3ZWlnaHQgPSAyLAogICAgb3BhY2l0eSA9IDEsCiAgICBjb2xvciA9ICJ3aGl0ZSIsCiAgICBkYXNoQXJyYXkgPSAiMyIsCiAgICBmaWxsT3BhY2l0eSA9IDAuNywKICAgIGhpZ2hsaWdodCA9IGhpZ2hsaWdodE9wdGlvbnMoCiAgICAgIHdlaWdodCA9IDUsCiAgICAgIGNvbG9yID0gIiM2NjYiLAogICAgICBkYXNoQXJyYXkgPSAiIiwKICAgICAgZmlsbE9wYWNpdHkgPSAwLjcsCiAgICAgIGJyaW5nVG9Gcm9udCA9IFRSVUUpLAogICAgbGFiZWwgPSBsYWJlbHNfNSwKICAgIGxhYmVsT3B0aW9ucyA9IGxhYmVsT3B0aW9ucyhzdHlsZSA9IGxpc3QoImZvbnQtd2VpZ2h0IiA9ICJub3JtYWwiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFkZGluZyA9ICIzcHggOHB4IiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dHNpemUgPSAiMTVweCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlyZWN0aW9uID0gImF1dG8iKSkgJT4lIAogIGFkZExlZ2VuZChwYWwgPSBwYWxfNSwgdmFsdWVzID0gbGV0YWxpZGFkZV9yZWdpb2VzX29yZGVtWywyXSwgb3BhY2l0eSA9IDAuNywgdGl0bGUgPSAiVGF4YSBkZSBMZXRhbGlkYWRlICglKSBwb3IgQVJTIiwKICAgICAgICAgICAgcG9zaXRpb24gPSAiYm90dG9tcmlnaHQiKQoKYnJvd3NhYmxlKAogIHRhZ0xpc3QobGlzdCgKICAgIHRhZ3MkZGl2KAogICAgICBzdHlsZSA9ICd3aWR0aDo1MCU7ZGlzcGxheTpibG9jaztmbG9hdDpsZWZ0OycsCiAgICAgIGxldGFsaWRhZGVfcmVnaW9lc19tYXBhCiAgICApLAogICAgdGFncyRkaXYoCiAgICAgIHN0eWxlID0gJ3dpZHRoOjUwJTtkaXNwbGF5OmJsb2NrO2Zsb2F0OmxlZnQ7JywKICAgICAgbGV0YWxpZGFkZV9yZWdpb2VzX2dyYWZpY29faW50ZXJhdGl2bwogICAgKQogICkpCikKYGBgCgoKIyMjIyBFdm9sdcOnw6NvIHBvciBBUlMKCjxicj4KClNlZ3VuZG8gZXN0ZSBncsOhZmljbyBkZSBsaW5oYXMsIHBvZGVtb3MgdmVyIHF1ZSBhcyBBUlNzIGRvIE5vcnRlLCBkbyBDZW50cm8sIGRlIExpc2JvYSBlIFZhbGUgZG8gVGVqbyBlIGRvIEFsZ2FydmUgYXByZXNlbnRhbSB1bSBjb21wb3J0YW1lbnRvIHNlbWVsaGFudGUgZW1ib3JhIGVtIGRpZmVyZW50ZXMgcHJvcG9yw6fDtWVzLCBjb20gb3MgdmFsb3JlcyBtw6F4aW1vcyBlbnRyZSBtYWlvIGUganVuaG8uIEEgcGFydGlyIGRlIGp1bmhvIG9zIHZhbG9yZXMgdMOqbSB2aW5kbyBhIGRlY3Jlc2NlciBwZWxhcyByYXrDtWVzIG1lbmNpb25hZGFzIGFudGVyaW9ybWVudGUsIGVzcGVjaWFsbWVudGUgYSBBUlMgZG8gQWxnYXJ2ZSBlbSBxdWUgZXNzYSBkaW1pbnVpw6fDo28gZm9pIG1haXMgYWNlbnR1YWRhLCBldmVudHVhbG1lbnRlIGRldmlkbyDDoCBtYWlvciBpbmNpZMOqbmNpYSBlbSBpbmRpdsOtZHVvcyBtYWlzIGpvdmVucy4KCk5vIGNhc28gZG9zIEHDp29yZXMgb2NvcnJldSB1bSBhdW1lbnRvIGFicnVwdG8gZGEgdGF4YSBkZSBsZXRhbGlkYWRlLCBlbSBxdWUgbm8gc2V1IHBpY28gY2VyY2EgZGUgMTElIGRhcyBwZXNzb2FzIGluZmV0YWRhcyBtb3JyaWFtLiBEZXNkZSBqdW5obyBlc3RhIHRheGEgdGVtIHZpbmRvIGEgZGltaW51aXIsIHBvc3NpdmVsbWVudGUgZGV2aWRvIMOgIGVzdHJhdMOpZ2lhIGltcGxlbWVudGFkYSBkYSByZWFsaXphw6fDo28gZGUgdW1hIHRlc3RhZ2VtIGVtIGdyYW5kZSBlc2NhbGEsIGRldGV0YW5kbyBhc3NpbSBvcyBjYXNvcyBhc3NpbnRvbcOhdGljb3MgZSBtZW5vcyBncmF2ZXMuCgpBIEFSUyBkbyBBbGVudGVqbyBhcHJlc2VudGEgdW0gY29tcG9ydGFtZW50byBhdMOtcGljby4gT2NvcnJlIHVtIHBpY28gbm8gZGlhIDAzLzA0LzIwMjAgcXVlIHBvZGUgcmVwcmVzZW50YXIgYSBtb3J0ZSBkZSBwZXNzb2FzIGluZmV0YWRhcyBubyBpbsOtY2lvIGRhIHBhbmRlbWlhLCBubyBlbnRhbnRvIMOpIGludnVsZ2FyIHF1ZSB0ZW5oYW0gdG9kYXMgb2NvcnJpZG8gbm8gbWVzbW8gZGlhLiBEZSBzZWd1aWRhIGEgdGF4YSBkZSBsZXRhbGlkYWRlIHJlZ3Jlc3NhIGEgMCUsIG8gcXVlIGRlbW9uc3RyYSBxdWUgaG91dmUgdW0gbGFwc28gbm8gcmVnaXN0byBkb3Mgw7NiaXRvcy4gRW50cmUgbWFpbyBlIGp1bmhvIGEgdGF4YSBkZSBsZXRhbGlkYWRlIG1hbnRldmUtc2UgZW0gKnBsYXTDtCosIHNlbmRvIGlzc28gdGFtYsOpbSBpbmNvbXVtLiBEZSBzZWd1aWRhLCBhcHJlc2VudG91IHVtIGF1bWVudG8gYWJydXB0byBxdWUgcG9kZSBzZXIgZXhwbGljYWRvIHBlbG8gYXVtZW50byBkYSBpbmNpZMOqbmNpYSwgcG9zc2l2ZWxtZW50ZSBlbSBmYWl4YXMgZXTDoXJpYXMgbWFpcyB2ZWxoYXMuIERlc2RlIGp1bGhvLCB0ZW0gZGVtb25zdHJhZG8gdW0gY29tcG9ydGFtZW50byBzZW1lbGhhbnRlIMOgcyBvdXRyYXMgQVJTcywgY29tIHVtYSBkZXNjaWRhIGRhIHRheGEgZGUgbGV0YWxpZGFkZS4KCk5hIE1hZGVpcmEgYSB0YXhhIGRlIGxldGFsaWRhZGUgw6kgemVybywgdW1hIHZleiBxdWUgbsOjbyBzZSB2ZXJpZmljYXJhbSDDs2JpdG9zIG5lc3RhIHJlZ2nDo28uCgpgYGB7ciwgd2FybmluZz1GQUxTRX0KI0NyaWFyIHRhYmVsYSBjb20gdW1hIGNvbHVuYSBwYXJhIGRhdGEgZSBvdXRyYXMgY29sdW5hcyB1bWEgcGFyYSBjYWRhIHJlZ2nDo28gdGVuZG8gbMOhIG9zIHZhbG9yZXMgZGEgbGV0YWxpZGFkZSBkacOhcmlhIGUgZGFyIG5vbWVzIMOgcyBjb2x1bmFzCmxldGFsaWRhZGVfcmVnaW9lc190ZW1wbyA8LSBjYmluZChjb3ZpZDE5cHQkZGF0YSwgYXMuZGF0YS5mcmFtZSgoY292aWQxOXB0Wyw0OTo1NV0vY292aWQxOXB0Wyw0OjEwXSkpKjEwMCkKbmFtZXMobGV0YWxpZGFkZV9yZWdpb2VzX3RlbXBvKSA8LSBjKCJEYXRhIiwgIk5vcnRlIiwgIkNlbnRybyIsICJMaXNib2EgZSBWYWxlIGRvIFRlam8iLCAiQWxlbnRlam8iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBbGdhcnZlIiwgIkHDp29yZXMiLCAiTWFkZWlyYSIpCgojRmF6ZXIgbWVsdCBwYXJhIHBvZGVyIGZhemVyIG8gZ3LDoWZpY28KbGV0YWxpZGFkZV9yZWdpb2VzX3RlbXBvX21lbHQgPC0gbWVsdChsZXRhbGlkYWRlX3JlZ2lvZXNfdGVtcG8sIGlkLnZhcnMgPSAiRGF0YSIpCm5hbWVzKGxldGFsaWRhZGVfcmVnaW9lc190ZW1wb19tZWx0KSA9IGMoIkRhdGEiLCAiUmVnaWFvIiwgIkxldGFsaWRhZGUiKQoKI0ZhemVyIG8gZ3LDoWZpY28gZGUgbGluaGFzIGNvbSBkYXRhIG5vIGVpeG8gZG8geCwgbGV0YWxpZGFkZSBubyBlaXhvIGRvIHkgZSByZWdpYW8gZW0gY2FkYSBsaW5oYQpsZXRhbGlkYWRlX3JlZ2lvZXNfdGVtcG9fZ3JhZmljbyA8LSBnZ3Bsb3QobGV0YWxpZGFkZV9yZWdpb2VzX3RlbXBvX21lbHQsIGFlcyh4ID0gRGF0YSwgeSA9IExldGFsaWRhZGUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9IFJlZ2lhbykpICsKICBnZW9tX2xpbmUoc2l6ZT0wLjUpICsKICBnZW9tX3BvaW50KHNpemU9MC4xLCBhZXModGV4dCA9IHBhc3RlKCAnRGF0YTogJywgRGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnPGJyPkFSUyA6JywgUmVnaWFvLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+VGF4YSBkZSBMZXRhbGlkYWRlICglKSA6JywgTGV0YWxpZGFkZSApKSkgKwogIGxhYnMoeCA9ICIiLAogICAgICAgeSA9IkxldGFsaWRhZGUgKCUpIikgKwogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKSArCiAgc2NhbGVfeF9kYXRlKGJyZWFrcyA9ICIzIG1vbnRocyIsIGRhdGVfbGFiZWxzID0gIiViICVkIikKCiNUb3JuYXIgZ3LDoWZpY28gaW50ZXJhdGl2bwpnZ3Bsb3RseShsZXRhbGlkYWRlX3JlZ2lvZXNfdGVtcG9fZ3JhZmljbywgdG9vbHRpcCA9ICJ0ZXh0IikgJT4lIAogIGxheW91dCh5YXhpcyA9IGxpc3QodGl0bGUgPSBwYXN0ZTAoYyhyZXAoIiZuYnNwOyIsIDIwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRheGEgZGUgTGV0YWxpZGFkZSAoJSkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXAoIiZuYnNwOyIsIDIwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCJcbiZuYnNwOyIsIDIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlID0gIiIpKSwKICAgICAgICAgbGVnZW5kID0gbGlzdCh4ID0gMSwgeSA9IDApKQpgYGAKCgojIyAqKkludGVybmFtZW50b3MqKiB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30KKioqCgpVbSBmYXRvciBtdWl0byBpbXBvcnRhbnRlIGEgdGVyIGVtIGNvbnRhIG5vIGRlY29ycmVyIGRlIHVtYSBwYW5kZW1pYSDDqSwgbsOjbyBzw7MgbyBuw7ptZXJvIGRlIHBlc3NvYXMgaW5mZXRhZGFzLCBtYXMgdGFtYsOpbSBvIG7Dum1lcm8gZGUgcGVzc29hcyBxdWUgbmVjZXNzaXRhIGRlIGFjb21wYW5oYW1lbnRvIGhvc3BpdGFsYXIgcGFyYSBpbXBlZGlyIGEgZmFsw6puY2lhIGRvIHNpc3RlbWEgZGUgc2HDumRlLgoKPGJyPgoKIyMjIEV2b2x1w6fDo28gZG8gTsO6bWVybyBkZSBJbnRlcm5hZG9zCgo8YnI+CgpBbyByZWFsaXphciBhIGludGVycHJldGHDp8OjbyBkZXN0ZSBncsOhZmljbyB2ZXJpZmljw6Ftb3MgcXVlIG5vIGluw61jaW8gZGEgcGFuZGVtaWEgbyBuw7ptZXJvIGRlIGludGVybmFkb3MgYXVtZW50b3UgZXhwb25lbmNpYWxtZW50ZSwgdGVuZG8gYXRpbmdpZG8gbyB2YWxvciBtw6F4aW1vIG5vIGRpYSAxNi8wNC8yMDIwLiDDiSBkZSBzYWxpZW50YXIgcXVlIG5lc3RhIGZhc2UgYWluZGEgbsOjbyBleGlzdGlhIG8gY29uaGVjaW1lbnRvIG5lY2Vzc8OhcmlvIHBhcmEgYXR1YXIgbWVkaWNhbWVudGUgc29icmUgb3MgY2Fzb3MgbWFpcyBncmF2ZXMgZGEgZG9lbsOnYSBlLCB0YW1iw6ltIHBvciBlc3NhIGZhbHRhIGRlIGNvbmhlY2ltZW50bywgcmVjb3JyaWEtc2UgYSB1bSBpbnRlcm5hbWVudG8gbWFpcyBwcmVjb2NlLiBQYXJhIGFsw6ltIGRpc3NvLCB1bWEgZGFzIGZhaXhhcyBldMOhcmlhcyBtYWlzIGF0aW5naWRhcyBmb2kgYSBkb3MgODArIGFub3MsIGxldmFuZG8sIG5hdHVyYWxtZW50ZSwgYSB1bSBtYWlvciBuw7ptZXJvIGRlIGNvbXBsaWNhw6fDtWVzLiBEZXNkZSBlc3NlIHBpY28gYXTDqSBtZWFkb3MgZGUganVuaG8sIG8gbsO6bWVybyBkZSBpbnRlcm5hZG9zIGZvaSBkaW1pbnVpbmRvLCBzZWd1aW5kby1zZSB1bSBsaWdlaXJvIGF1bWVudG8gYXTDqSBqdWxobyBjb20gbm92YSBkZXNjaWRhIGF0w6kgc2V0ZW1icm8uIEEgcGFydGlyIGRlIHNldGVtYnJvIG8gbsO6bWVybyBkZSBpbnRlcm5hZG9zIHRlbSB2aW5kbyBhIGFjb21wYW5oYXIgbyBhdW1lbnRvIG5vIG7Dum1lcm8gZGUgY2Fzb3MuCgpSZWxhdGl2YW1lbnRhIGFvcyBpbnRlcm5hZG9zIG5hIHVuaWRhZGUgZGUgY3VpZGFkb3MgaW50ZW5zaXZvcyAoVUNJKSwgaG91dmUgdW0gYXVtZW50byBjb25jb3JkYW50ZSBjb20gbyBhdW1lbnRvIGRvcyBpbnRlcm5hZG9zLCBlbWJvcmEgZW0gbXVpdG8gbWVub3IgZXNjYWxhLiBBIHBhcnRpciBkbyBkaWEgNy8wNC8yMDIwIGZvaSBkaW1pbnVpbmRvIGdyYWR1YWxtZW50ZSB0ZW5kbyB2b2x0YWRvIGEgYXVtZW50YXIgdGFtYsOpbSBubyBpbsOtY2lvIGRlIHNldGVtYnJvLgoKYGBge3IsIHdhcm5pbmc9RkFMU0V9CiNGYXplciBtZWx0IGRhcyBjb2x1bmFzIGRhdGEsIGludGVybmFkb3MgZSBpbnRlcm5hZG9zIFVDSSBwYXJhIHRlciBuw7ptZXJvIGRlIGludGVybmFkb3MgZW0gY2FkYSBkaWEKaW50ZXJuYWRvcyA8LSBtZWx0KGNvdmlkMTlwdFssYygxLCAxNSwgODgsIDE2KV0sIGlkLnZhcnMgPSAiZGF0YSIpCgojTXVkYXIgbyBub21lIGRvIGNvbnRlw7pkbyBkYSBjb2x1bmEgZG9zIGludGVybmFkb3MgcGFyYSBpbnRlcm5hZG9zIG91IGludGVybmFkb3MgVUNJCmxldmVscyhpbnRlcm5hZG9zJHZhcmlhYmxlKVtsZXZlbHMoaW50ZXJuYWRvcyR2YXJpYWJsZSk9PSJpbnRlcm5hZG9zIl0gPC0gIkludGVybmFkb3MgVG90YWwiCmxldmVscyhpbnRlcm5hZG9zJHZhcmlhYmxlKVtsZXZlbHMoaW50ZXJuYWRvcyR2YXJpYWJsZSk9PSJpbnRlcm5hZG9zX3VjaSJdIDwtICJJbnRlcm5hZG9zIFVDSSIKbGV2ZWxzKGludGVybmFkb3MkdmFyaWFibGUpW2xldmVscyhpbnRlcm5hZG9zJHZhcmlhYmxlKT09ImludGVybmFkb3NfZW5mZXJtYXJpYSJdIDwtICJJbnRlcm5hZG9zIEVuZmVybWFyaWEiCm5hbWVzKGludGVybmFkb3MpID0gYygiZGF0YSIsICJ0aXBvX2ludGVybmFtZW50byIsICJpbnRlcm5hZG9zIikKCiNGYXplciBncsOhZmljbyBkZSBsaW5oYXMgY29tIGRhdGEgbm8gZWl4byBkbyB4LCBuw7ptZXJvIGRlIGludGVybmFkb3Mgbm8gZWl4byBkbyB5IGUgdGlwbyBkZSBpbnRlcm5hbWVudG8gbmFzIGxpbmhhcwppbnRlcm5hZG9zX2dyYWZpY28gPC0gZ2dwbG90KGludGVybmFkb3MsIGFlcyh4ID0gZGF0YSwgeSA9aW50ZXJuYWRvcywgY29sb3IgPSB0aXBvX2ludGVybmFtZW50bykpICsKICBnZW9tX2xpbmUoc2l6ZSA9IDAuNSkgKwogIGdlb21fcG9pbnQoc2l6ZT0wLjEsIGFlcyh0ZXh0ID0gcGFzdGUoICdEYXRhOiAnLCBkYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+VGlwbyBkZSBJbnRlcm5hbWVudG8gOicsIHRpcG9faW50ZXJuYW1lbnRvLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+TsK6IGRlIEludGVybmFkb3MgOicsIGludGVybmFkb3MgKSkpICsKICBsYWJzKHggPSAiIiwgY29sb3IgPSAiIikgKwogIHRoZW1lKGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSA3KSkgKwogIHNjYWxlX3hfZGF0ZShicmVha3MgPSAiMyBtb250aHMiLCBkYXRlX2xhYmVscyA9ICIlYiAlZCIpCgojVG9ybmFyIGdyw6FmaWNvIGludGVyYXRpdm8KZ2dwbG90bHkoaW50ZXJuYWRvc19ncmFmaWNvLCB0b29sdGlwID0gInRleHQiKSAlPiUgCiAgbGF5b3V0KHlheGlzID0gbGlzdCh0aXRsZSA9IHBhc3RlMChjKHJlcCgiJm5ic3A7IiwgMjApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTsO6bWVybyBkZSBJbnRlcm5hZG9zIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCImbmJzcDsiLCAyMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcCgiXG4mbmJzcDsiLCAyKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xsYXBzZSA9ICIiKSksCiAgICAgICAgIGxlZ2VuZCA9IGxpc3QoeCA9IDEsIHkgPSAwKSkKYGBgCgoKIyMjIEV2b2x1w6fDo28gZGEgVGF4YSBkZSBJbnRlcm5hbWVudG8KCjxicj4KCk5vIGluw61jaW8gZGEgcGFuZGVtaWEgYXBlbmFzIG9zIGNhc29zIGdyYXZlcyBwcm9jdXJhdmFtIGFqdWRhIG3DqWRpY2EgZSwgcG9yIGlzc28sIGVyYW0gb3Mgw7puaWNvcyBhIHNlcmVtIGRpYWdub3N0aWNhZG9zLCBvIHF1ZSBqdXN0aWZpY2EgYSB0YXhhIGRlIGludGVybmFtZW50byBkZSAxMDAlLiBEZSBzZWd1aWRhIGhvdXZlIHVtYSBkZXNjaWRhIGFicnVwdGEsIGV4cGxpY2FkYSBwZWxvIGF1bWVudG8gZG8gZGlhZ27Ds3N0aWNvIGRlIGNhc29zIG1lbm9zIGdyYXZlcy4gTm8gZmluYWwgZGUgbWFyw6dvIGhvdXZlIHVtIGxpZ2Vpcm8gYXVtZW50byBuYSB0YXhhIGRlIGludGVybmFkb3MuIFBvc3Rlcmlvcm1lbnRlIGhvdXZlIHVtYSBkaW1pbnVpw6fDo28gZGVzdGEgdGF4YSwgcG9zc2l2ZWxtZW50ZSBkZXZpZG8gYSB1bSBtYWlvciBjb25oZWNpbWVudG8gZGVzdGEgY29uZGnDp8OjbyBtw6lkaWNhIGFzc2ltIGNvbW8gdW1hIG1haW9yIGluY2lkw6puY2lhIG5hcyBmYWl4YXMgZXTDoXJpYXMgbWFpcyBqb3ZlbnMuIEEgcGFydGlyIGRlIHNldGVtYnJvIGEgdGF4YSBhcHJlc2VudGEgdW0gY29tcG9ydGFtZW50byBsaWdlaXJhbWVudGUgY3Jlc2NlbnRlLCBxdWUgcG9kZSBkZXZlci1zZSBhIHVtIG5vdm8gYXVtZW50byBkbyBuw7ptZXJvIGRlIGNhc29zIG5hcyBmYWl4YXMgZXTDoXJpYXMgbWFpcyB2ZWxoYXMgKGdyw6FmaWNvIGRhIEV2b2x1w6fDo28gZGEgSW5jaWTDqm5jaWEgcG9yIEZhaXhhIEV0w6FyaWEpLgoKYGBge3IsIHdhcm5pbmc9RkFMU0V9CiNGYXplciBtZWx0IHBhcmEgdGVyIHRhYmVsYSBjb20gY29sdW5hIGRhIGRhdGEsIGNvbHVuYSBkbyB0aXBvIGRlIGludGVybmFtZW50byBlIGNvbHVuYSBjb20gcGVyY2VudGFnZW0gZGUgaW50ZXJuYWRvcyBxdWUgc8OjbyBvcyBpbnRlcm5hZG9zIGEgZGl2aWRpciBwZWxvcyBjb25maXJtYWRvcyBlIGRhciBub21lcyDDoHMgY29sdW5hcwppbnRlcm5hZG9zX2NvbmZpcm1hZG9zIDwtIG1lbHQoKGNiaW5kKGNvdmlkMTlwdCRkYXRhLCAoYXMuZGF0YS5mcmFtZShsYXBwbHkoY292aWQxOXB0WyxjKDE1LCA4OCwgMTYpXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24oeCkgeyh4L2NvdmlkMTlwdFssIDNdKSoxMDB9KSkpKSksIGlkLnZhcnMgPSAiY292aWQxOXB0JGRhdGEiKQpuYW1lcyhpbnRlcm5hZG9zX2NvbmZpcm1hZG9zKSA8LSBjKCJkYXRhIiwgImludGVybmFkb3MiLCAicGVyY2VudGFnZW0iKQoKI011ZGFyIG8gbm9tZSBkbyBjb250ZcO6ZG8gZGEgY29sdW5hIGRvcyBpbnRlcm5hZG9zIHBhcmEgaW50ZXJuYWRvcyBvdSBpbnRlcm5hZG9zIFVDSQpsZXZlbHMoaW50ZXJuYWRvc19jb25maXJtYWRvcyRpbnRlcm5hZG9zKVtsZXZlbHMoaW50ZXJuYWRvc19jb25maXJtYWRvcyRpbnRlcm5hZG9zKT09ImNvbmZpcm1hZG9zIl0gPC0gIiBJbnRlcm5hZG9zIFRvdGFsIgpsZXZlbHMoaW50ZXJuYWRvc19jb25maXJtYWRvcyRpbnRlcm5hZG9zKVtsZXZlbHMoaW50ZXJuYWRvc19jb25maXJtYWRvcyRpbnRlcm5hZG9zKT09ImNvbmZpcm1hZG9zLjEiXSA8LSAiSW50ZXJuYWRvcyBFbmZlcm1hcmlhIgpsZXZlbHMoaW50ZXJuYWRvc19jb25maXJtYWRvcyRpbnRlcm5hZG9zKVtsZXZlbHMoaW50ZXJuYWRvc19jb25maXJtYWRvcyRpbnRlcm5hZG9zKT09ImNvbmZpcm1hZG9zLjIiXSA8LSAiSW50ZXJuYWRvcyBVQ0kiCgojRmF6ZXIgZ3LDoWZpY28gZGUgbGluaGFzIGNvbSBkYXRhIG5vIGVpeG8gZG8geCwgcGVyY2VudGFnZW0gaW50ZXJuYWRvcyBubyBlaXhvIGRvIHkgZSB0aXBvIGRlIGludGVybmFtZW50byBlbSBjYWRhIGxpbmhhCmludGVybmFkb3NfY29uZmlybWFkb3NfZ3JhZmljbyA8LSBnZ3Bsb3QoaW50ZXJuYWRvc19jb25maXJtYWRvcywgYWVzKHggPSBkYXRhLCB5ID0gcGVyY2VudGFnZW0sIGNvbG9yID0gaW50ZXJuYWRvcykpICsKICBnZW9tX2xpbmUoc2l6ZSA9IDAuNSkgKwogIGdlb21fcG9pbnQoc2l6ZT0wLjEsIGFlcyh0ZXh0ID0gcGFzdGUoICdEYXRhOiAnLCBkYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc8YnI+VGlwbyBkZSBJbnRlcm5hbWVudG8gOicsIGludGVybmFkb3MsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJzxicj5UYXhhIGRlIEludGVybmFtZW50byAoJSkgOicsIHBlcmNlbnRhZ2VtICkpKSArCiAgbGFicyh4ID0gIiIsIGNvbG9yID0gIiIpICsKICB0aGVtZShheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gNykpICsKICBzY2FsZV94X2RhdGUoYnJlYWtzID0gIjMgbW9udGhzIiwgZGF0ZV9sYWJlbHMgPSAiJWIgJWQiKQoKI1Rvcm5hciBncsOhZmljbyBpbnRlcmF0aXZvCmdncGxvdGx5KGludGVybmFkb3NfY29uZmlybWFkb3NfZ3JhZmljbywgdG9vbHRpcCA9ICJ0ZXh0IikgJT4lIAogIGxheW91dCh5YXhpcyA9IGxpc3QodGl0bGUgPSBwYXN0ZTAoYyhyZXAoIiZuYnNwOyIsIDIwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRheGEgZGUgSW50ZXJuYW1lbnRvICglKSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcCgiJm5ic3A7IiwgMjApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXAoIlxuJm5ic3A7IiwgMikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sbGFwc2UgPSAiIikpLAogICAgICAgICBsZWdlbmQgPSBsaXN0KHggPSAxLCB5ID0gMCkpCmBgYAoKIyMjIFLDoWNpbyBlbnRyZSBJbnRlcm5hZG9zIFVDSSBlIEludGVybmFkb3MKCjxicj4KCk5lc3RlIGdyw6FmaWNvIHBvZGVtb3MgdmVyIHF1ZSBubyBpbsOtY2lvIGRhIHBhbmRlbWlhLCB1bWEgdmV6IHF1ZSBhcGVuYXMgb3MgY2Fzb3MgbWFpcyBncmF2ZXMgZXJhbSBkaWFnbm9zdGljYWRvcywgY2VyY2EgZGUgMzAlIGRvcyBpbnRlcm5hZG9zIGVuY29udHJhdmFtLXNlIG5hIHVuaWRhZGUgZGUgY3VpZGFkb3MgaW50ZW5zaXZvcy4gCkRlc2RlIG8gaW7DrWNpbyBkZSBhYnJpbCBlc3RlIHLDoWNpbyB0ZW0gdmluZG8gYSBkaW1pbnVpci4gVGV2ZSB1bSBhdW1lbnRvIGxpZ2Vpcm8gbm8gZGlhIDE2IGRlIG1haW8sIHByb3ZhdmVsbWVudGUgcmVzdWx0YW50ZSBkb3MgNTIgc3VydG9zIGF0aXZvcyBlbSBsYXJlcyBkZSBpZG9zb3MgZXhpc3RlbnRlcyBkZSAxIGEgNyBkZSBtYWlvLiBObyBpbsOtY2lvIGRvIHZlcsOjbyBob3V2ZSB1bSBub3ZvIGF1bWVudG8gcHJvdmF2ZWxtZW50ZSB0YW1iw6ltIHJlc3VsdGFudGUgZG9zIHN1cnRvcyBhdGl2b3MgZW0gZXN0cnV0dXJhcyByZXNpZGVuY2lhaXMgcGFyYSBpZG9zb3MuCgpQb3N0ZXJpb3JtZW50ZSBvIHLDoWNpbyBmb2kgZGltaW51aW5kbyBkZSBmb3JtYSBjb25zaWRlcsOhdmVsIGF0w6kgZGlhIDEwIGRlIGFnb3N0bywgb25kZSBhdGluZ2l1IG8gc2V1IG3DrW5pbW8gY29tIGNlcmNhIGRlIDclLiBEZSBzZWd1aWRhLCBvIHLDoWNpbyB0ZW0gdmluZG8gbm92YW1lbnRlIGEgYXVtZW50YXIgZGV2aWRvIGEgdW0gYXVtZW50byBkYSBpbmNpZMOqbmNpYSBuYSBwb3B1bGHDp8OjbyBtYWlzIHZlbGhhIChncsOhZmljbyBFdm9sdcOnw6NvIGRhIEluY2lkw6puY2lhIHBvciBGYWl4YSBFdMOhcmlhKS4KCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojRmF6ZXIgbyByw6FjaW8KcmFjaW9faW50ZXJuYWRvcyA8LSBjYmluZChjb3ZpZDE5cHQkZGF0YSwgYXMuZGF0YS5mcmFtZSgoY292aWQxOXB0JGludGVybmFkb3NfdWNpL2NvdmlkMTlwdCRpbnRlcm5hZG9zKSoxMDApKQpuYW1lcyhyYWNpb19pbnRlcm5hZG9zKSA9IGMoIkRhdGEiLCAiUmFjaW8iKQoKI0ZhemVyIG8gZ3LDoWZpY28KcmFjaW9faW50ZXJuYWRvc19ncmFmaWNvIDwtIGdncGxvdChyYWNpb19pbnRlcm5hZG9zLCBhZXMoeCA9IERhdGEsIHkgPSBSYWNpbykpICsgCiAgZ2VvbV9saW5lKGNvbG9yID0gInRvbWF0bzQiLCBzaXplPTAuNSkgKwogIGdlb21fcG9pbnQoY29sb3IgPSAidG9tYXRvNCIsIHNpemU9MC4xLCBhZXModGV4dCA9IHBhc3RlKCAnRGF0YTogJywgRGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnPGJyPlLDoWNpbyAoJSkgOicsIFJhY2lvKSkpICsKICBsYWJzKHggPSAiIiwKICAgICAgIHkgPSAiUsOhY2lvICglKSIpICsKICBzY2FsZV94X2RhdGUoYnJlYWtzID0gIjMgbW9udGhzIiwgZGF0ZV9sYWJlbHMgPSAiJWIgJWQiKQoKCiNUb3JuYXIgaW50ZXJhdGl2bwpnZ3Bsb3RseShyYWNpb19pbnRlcm5hZG9zX2dyYWZpY28sIHRvb2x0aXAgPSAidGV4dCIpCgpgYGAKCjxicj4KCiMjICoqUmVjdXBlcmFkb3MqKiB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30KKioqCgrDiSBpbXBvcnRhbnRlIGFuYWxpc2FyLXNlIG8gbsO6bWVybyBkZSByZWN1cGVyYWRvcyBwYXJhIHNlIHBvZGVyIGF2YWxpYXIgZGUgcXVlIGZvcm1hIG8gdGlwbyBkZSB0cmF0YW1lbnRvIGUvb3UgY3VpZGFkb3MgYXBsaWNhZG9zIGVzdMOjbyBhIHNlciBlZmljYXplcy4KCjxicj4KCiMjIyBFdm9sdcOnw6NvIGRhIFRheGEgZGUgUmVjdXBlcmFkb3MKCjxicj4KCk5vcyBtZXNlcyBkZSBtYXLDp28gZSBhYnJpbCBhIHRheGEgZGUgcmVjdXBlcmFkb3MgZXJhIGJhc3RhbnRlIGJhaXhhLiBJc3RvIHBvZGUgc2VyIGp1c3RpZmljYWRvIHBlbG8gZmFjdG8gZGUgYXBlbmFzIG9zIGNhc29zIGdyYXZlcyB0ZXJlbSBzaWRvIGRpYWdub3N0aWNhZG9zIG5lc3RhIGZhc2UuIEEgcGFydGlyIGRlIGFicmlsLCBhIHRheGEgZGUgcmVjdXBlcmFkb3Mgc29mcmV1IHVtIGNyZXNjaW1lbnRvIGRldmlkbyBhbyBhdW1lbnRvIGRvIG7Dum1lcm8gZGUgZGlhZ27Ds3N0aWNvcyBkZSBjYXNvcyBtZW5vcyBncmF2ZXMuIE5vIGRpYSAyNC8wNS8yMDIwLCBhIHRheGEgZGUgcmVjdXBlcmFkb3MgdGV2ZSB1bWEgc3ViaWRhIGFicnVwdGEsIHF1ZSBwb2RlIGRldmVyLXNlIGEgdW0gbGFwc28gbm8gcmVnaXN0byBkb3MgcmVjdXBlcmFkb3MuIE5vIGRpYSAyNS8wOC8yMDIwIG9jb3JyZXUgbyBwaWNvLiBEZXNkZSBlbnTDo28sIGEgdGF4YSB0ZW0gdmluZG8gYSBkaW1pbnVpciBkZSBmb3JtYSBncmFkdWFsLCBvIHF1ZSBwb2RlIHNlciBkZXZpZG8gYW8gZ3JhbmRlIGF1bWVudG8gZG8gbsO6bWVybyBkZSBjYXNvcyB2ZXJpZmljYWRvcyBlbSBzZXRlbWJybywgb3MgcXVhaXMgYWluZGEgbsOjbyB0aXZlcmFtIHRlbXBvIHBhcmEgcmVjdXBlcmFyLgoKYGBge3IsIHdhcm5pbmc9RkFMU0V9CiNDcmlhciB0YWJlbGEgY29tIGNvbHVuYSBwYXJhIGRhdGEgZSBvdXRyYSBjb2x1bmEgcGFyYSBhIHBlcmNlbnRhZ2VtIGRlIHJlY3VwZXJhZG9zIGVtIGNhZGEgZGlhIGUgZGFyIG5vbWVzIMOgcyBjb2x1bmFzCnJlY3VwZXJhZG9zIDwtIGNiaW5kKGNvdmlkMTlwdCRkYXRhLCBhcy5kYXRhLmZyYW1lKChjb3ZpZDE5cHQkcmVjdXBlcmFkb3MgLyBjb3ZpZDE5cHQkY29uZmlybWFkb3MpKjEwMCkpCm5hbWVzKHJlY3VwZXJhZG9zKSA8LSBjKCJEYXRhIiwgIlJlY3VwZXJhZG9zIikKCiNGYXplciBncsOhZmljbyBkZSBsaW5oYXMgY29tIGRhdGEgbm8gZWl4byBkbyB4IGUgcGVyY2VudGFnZW0gcmVjdXBlcmFkb3Mgbm8gZWl4byB5CnJlY3VwZXJhZG9zX2dyYWZpY28gPC0gZ2dwbG90KHJlY3VwZXJhZG9zLCBhZXMoeCA9IERhdGEsIHkgPSBSZWN1cGVyYWRvcykpICsKICBnZW9tX2xpbmUoY29sb3IgPSAic2FsbW9uMSIsIHNpemUgPSAwLjUpICsKICBnZW9tX3BvaW50KGNvbG9yID0gInNhbG1vbjEiLCBzaXplPTAuMSwgYWVzKHRleHQgPSBwYXN0ZSggJ0RhdGE6ICcsIERhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJzxicj5UYXhhIGRlIFJlY3VwZXJhZG9zICglKSA6JywgUmVjdXBlcmFkb3MpKSkgKwogIGxhYnMoeCA9ICIiLAogICAgICAgeSA9ICJUYXhhIGRlIFJlY3VwZXJhZG9zICglKSIpICsKICB0aGVtZShheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSkgKwogIHNjYWxlX3hfZGF0ZShicmVha3MgPSAiMyBtb250aHMiLCBkYXRlX2xhYmVscyA9ICIlYiAlZCIpCgojVG9ybmFyIGdyw6FmaWNvIGludGVyYXRpdm8KZ2dwbG90bHkocmVjdXBlcmFkb3NfZ3JhZmljbywgdG9vbHRpcCA9ICJ0ZXh0IikgJT4lIAogIGxheW91dCh5YXhpcyA9IGxpc3QodGl0bGUgPSBwYXN0ZTAoYyhyZXAoIiZuYnNwOyIsIDIwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRheGEgZGUgUmVjdXBlcmFkb3MgKCUpIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCImbmJzcDsiLCAyMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcCgiXG4mbmJzcDsiLCAyKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xsYXBzZSA9ICIiKSkpCmBgYAo=